ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2024-08-15 03:54:42
Exec Total Coverage
Lines: 98 7652 1.3%
Functions: 1 196 0.5%
Branches: 14 6421 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "subscr.h"
15 #include "zq/zquestdat.h"
16 #include "zq/zq_tiles.h"
17 #include "zq/zquest.h"
18 #include "tiles.h"
19 #include "zq/zq_misc.h"
20 #include "zq/zq_class.h"
21 #include "base/zsys.h"
22 #include "base/colors.h"
23 #include "qst.h"
24 #include "gui/jwin.h"
25 #include <base/new_menu.h>
26 #include "base/jwinfsel.h"
27 #include "zc/zc_custom.h"
28 #include "zq/questReport.h"
29 #include "dialog/info.h"
30 #include "dialog/scaletile.h"
31 #include "dialog/rotatetile.h"
32 #include "dialog/alert.h"
33 #include "drawing.h"
34 #include "colorname.h"
35 #include "zq/render.h"
36 #include "zinfo.h"
37 #include <fmt/format.h>
38 #include <functional>
39 #include "zq/moveinfo.h"
40 using std::set;
41
42 extern zcmodule moduledata;
43
44 #ifdef _MSC_VER
45 #define stricmp _stricmp
46 #endif
47
48 #define HIDE_USED (show_only_unused_tiles&1)
49 #define HIDE_UNUSED (show_only_unused_tiles&2)
50 #define HIDE_BLANK (show_only_unused_tiles&4)
51 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
52
53 extern void large_dialog(DIALOG *d);
54 static void massRecolorReset4Bit();
55 static void massRecolorReset8Bit();
56 static bool massRecolorSetup(int32_t cset);
57 static void massRecolorApply(int32_t tile);
58 extern int32_t last_droplist_sel;
59 extern int32_t TilePgCursorCol, CmbPgCursorCol;
60
61 int32_t ex=0;
62 int32_t nextcombo_fake_click=0;
63 int32_t invcol=0;
64 int32_t tthighlight = 1;
65 int32_t showcolortip = 1;
66 int32_t show_quartgrid = 0, hide_grid = 0;
67
68 tiledata *newundotilebuf;
69 std::vector<newcombo> undocombobuf;
70
71 BITMAP *selection_pattern;
72 byte selection_grid[18][18];
73 byte selection_anchor=0;
74
75 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
76 BITMAP *selecting_pattern;
77 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
78
79 extern int32_t bidcomboscripts_cnt;
80 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
81
82 BITMAP *intersection_pattern;
83
84 byte relational_template[48][4]=
85 {
86 { 0, 0, 0, 0 },
87 { 0, 1, 0, 0 },
88 { 1, 0, 0, 0 },
89 { 1, 1, 0, 0 },
90 { 0, 0, 1, 0 },
91 { 0, 1, 1, 0 },
92 { 1, 0, 1, 0 },
93 { 1, 1, 1, 0 },
94 { 0, 0, 0, 1 },
95 { 0, 1, 0, 1 },
96 { 1, 0, 0, 1 },
97 { 1, 1, 0, 1 },
98 { 0, 0, 1, 1 },
99 { 0, 1, 1, 1 },
100 { 1, 0, 1, 1 },
101 { 1, 1, 1, 1 },
102 { 0, 2, 0, 2 },
103 { 1, 2, 0, 2 },
104 { 0, 2, 1, 2 },
105 { 1, 2, 1, 2 },
106 { 3, 3, 0, 0 },
107 { 3, 3, 1, 0 },
108 { 3, 3, 0, 1 },
109 { 3, 3, 1, 1 },
110 { 3, 4, 0, 2 },
111 { 3, 4, 1, 2 },
112 { 2, 0, 2, 0 },
113 { 2, 1, 2, 0 },
114 { 2, 0, 2, 1 },
115 { 2, 1, 2, 1 },
116 { 2, 2, 2, 2 },
117 { 4, 3, 2, 0 },
118 { 4, 3, 2, 1 },
119 { 4, 4, 2, 2 },
120 { 0, 0, 3, 3 },
121 { 0, 1, 3, 3 },
122 { 1, 0, 3, 3 },
123 { 1, 1, 3, 3 },
124 { 0, 2, 3, 4 },
125 { 1, 2, 3, 4 },
126 { 3, 3, 3, 3 },
127 { 3, 4, 3, 4 },
128 { 2, 0, 4, 3 },
129 { 2, 1, 4, 3 },
130 { 2, 2, 4, 4 },
131 { 4, 3, 4, 3 },
132 { 4, 4, 4, 4 },
133 { 5, 5, 5, 5 }
134 };
135
136 byte dungeon_carving_template[96][4]=
137 {
138 { 0, 0, 0, 0 },
139 { 0, 1, 0, 0 },
140 { 1, 0, 0, 0 },
141 { 1, 1, 0, 0 },
142 { 0, 0, 1, 0 },
143 { 0, 1, 1, 0 },
144 { 1, 0, 1, 0 },
145 { 1, 1, 1, 0 },
146 { 0, 0, 0, 1 },
147 { 0, 1, 0, 1 },
148 { 1, 0, 0, 1 },
149 { 1, 1, 0, 1 },
150 { 0, 0, 1, 1 },
151 { 0, 1, 1, 1 },
152 { 1, 0, 1, 1 },
153 { 1, 1, 1, 1 },
154 { 0, 2, 0, 2 },
155 { 1, 2, 0, 2 },
156 { 0, 2, 1, 2 },
157 { 1, 2, 1, 2 },
158 { 3, 3, 0, 0 },
159 { 3, 3, 1, 0 },
160 { 3, 3, 0, 1 },
161 { 3, 3, 1, 1 },
162 { 3, 4, 0, 2 },
163 { 3, 4, 1, 2 },
164 { 2, 0, 2, 0 },
165 { 2, 1, 2, 0 },
166 { 2, 0, 2, 1 },
167 { 2, 1, 2, 1 },
168 { 2, 2, 2, 2 },
169 { 4, 3, 2, 0 },
170 { 4, 3, 2, 1 },
171 { 4, 4, 2, 2 },
172 { 0, 0, 3, 3 },
173 { 0, 1, 3, 3 },
174 { 1, 0, 3, 3 },
175 { 1, 1, 3, 3 },
176 { 0, 2, 3, 4 },
177 { 1, 2, 3, 4 },
178 { 3, 3, 3, 3 },
179 { 3, 4, 3, 4 },
180 { 2, 0, 4, 3 },
181 { 2, 1, 4, 3 },
182 { 2, 2, 4, 4 },
183 { 4, 3, 4, 3 },
184 { 4, 4, 4, 4 },
185 { 5, 5, 5, 5 },
186
187 { 5, 5, 5, 5 },
188 { 6, 6, 6, 6 },
189 { 7, 7, 7, 7 },
190 { 7, 6, 7, 6 },
191 { 8, 8, 8, 8 },
192 { 16, 6, 8, 15 },
193 { 7, 7, 8, 8 },
194 { 7, 6, 8, 15 },
195 { 9, 9, 9, 9 },
196 { 6, 6, 9, 9 },
197 { 7, 17, 14, 9 },
198 { 7, 6, 14, 9 },
199 { 8, 9, 8, 9 },
200 { 16, 6, 8, 9 },
201 { 7, 17, 8, 9 },
202 { 7, 6, 8, 9 },
203 { 10, 10, 10, 10 },
204 { 7, 10, 14, 10 },
205 { 16, 10, 8, 10 },
206 { 7, 10, 8, 10 },
207 { 11, 11, 11, 11 },
208 { 11, 11, 8, 15 },
209 { 11, 11, 14, 9 },
210 { 11, 11, 8, 9 },
211 { 14, 14, 14, 14 },
212 { 14, 14, 8, 14 },
213 { 12, 12, 12, 12 },
214 { 12, 6, 12, 15 },
215 { 12, 17, 12, 9 },
216 { 12, 6, 12, 9 },
217 { 12, 10, 12, 10 },
218 { 15, 15, 15, 15 },
219 { 15, 15, 15, 9 },
220 { 15, 14, 12, 10 },
221 { 13, 13, 13, 13 },
222 { 16, 6, 13, 13 },
223 { 7, 17, 13, 13 },
224 { 7, 6, 13, 13 },
225 { 16, 16, 16, 16 },
226 { 7, 16, 16, 16 },
227 { 11, 11, 13, 13 },
228 { 11, 14, 13, 16 },
229 { 17, 17, 17, 17 },
230 { 17, 6, 17, 17 },
231 { 12, 10, 17, 16 },
232 { 15, 11, 17, 13 },
233 { 15, 14, 17, 16 },
234 { 18, 18, 18, 18 }
235 };
236
237 struct tile_move_data
238 {
239 int32_t copies;
240 int32_t dest_first;
241 int32_t dest_last;
242 int32_t src_first;
243 int32_t src_last;
244 int32_t dest_top;
245 int32_t dest_bottom;
246 int32_t src_top;
247 int32_t src_bottom;
248 int32_t src_left, src_right;
249 int32_t src_width, src_height;
250 int32_t dest_left, dest_right;
251 int32_t dest_width, dest_height;
252 int32_t rows, cols;
253 bool rect, move;
254
255 tile_move_data()
256 {
257 copies = dest_first = dest_last = src_first = src_last = dest_top =
258 dest_bottom = src_top = src_bottom = src_left = src_right =
259 src_width = src_height = dest_left = dest_right = dest_width =
260 dest_height = rows = cols = 0;
261 rect = move = false;
262 }
263
264 tile_move_data(tile_move_data const& other)
265 {
266 copy(other);
267 }
268
269 tile_move_data& operator=(tile_move_data const& other)
270 {
271 copy(other);
272 return *this;
273 }
274
275 void copy(tile_move_data const& other)
276 {
277 copies = other.copies;
278 dest_first = other.dest_first;
279 dest_last = other.dest_last;
280 src_first = other.src_first;
281 src_last = other.src_last;
282 dest_top = other.dest_top;
283 dest_bottom = other.dest_bottom;
284 src_top = other.src_top;
285 src_bottom = other.src_bottom;
286 src_left = other.src_left;
287 src_right = other.src_right;
288 src_width = other.src_width;
289 src_height = other.src_height;
290 dest_left = other.dest_left;
291 dest_right = other.dest_right;
292 dest_width = other.dest_width;
293 dest_height = other.dest_height;
294 rows = other.rows;
295 cols = other.cols;
296 rect = other.rect;
297 move = other.move;
298 }
299
300 void flip()
301 {
302 zc_swap(src_first, dest_first);
303 zc_swap(src_last, dest_last);
304 zc_swap(src_top, dest_top);
305 zc_swap(src_bottom, dest_bottom);
306 zc_swap(src_left, dest_left);
307 zc_swap(src_right, dest_right);
308 zc_swap(src_width, dest_width);
309 zc_swap(src_height, dest_height);
310 }
311 };
312 bool do_movetile_united(tile_move_data const& tmd);
313
314 struct combo_move_data
315 {
316 int32_t tile, tile2, copy1, copycnt;
317 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
318 combo_move_data(combo_move_data const& other)
319 {
320 copy(other);
321 }
322 combo_move_data& operator=(combo_move_data const& other)
323 {
324 copy(other);
325 return *this;
326 }
327 void copy(combo_move_data const& other)
328 {
329 tile = other.tile;
330 tile2 = other.tile2;
331 copy1 = other.copy1;
332 copycnt = other.copycnt;
333 }
334
335 void flip()
336 {
337 int32_t tcnt = tile2-tile+1;
338 int32_t cpy2 = copy1+copycnt-1;
339 zc_swap(tile,copy1);
340 tile2 = cpy2;
341 copycnt = tcnt;
342 }
343 };
344
345 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
346 static optional<ComboMoveUndo> last_combo_move_list;
347 static optional<TileMoveUndo> last_tile_move_list;
348
349 int refl_flags = 0;
350 enum
351 {
352 REFL_90CW, REFL_HFLIP,
353 REFL_90CCW, REFL_VFLIP,
354 REFL_180, REFL_DBLFLIP,
355 REFL_MAX
356 };
357 const char *reflbtn_names[] =
358 {
359 "90 CW", "HFlip",
360 "90 CCW", "VFlip",
361 "180 Rot", "Diag Flip"
362 };
363 int bgmode = 0, xmode = 0;
364 const char *bgmodebtn_names[] =
365 {
366 "BG Color 0", "BG Trans."
367 };
368 const char *xmodebtn_names[] =
369 {
370 "X", "No X"
371 };
372 enum
373 {
374 XMODE_X, XMODE_NOX,
375 XMODE_MAX
376 };
377 enum
378 {
379 BGMODE_0, BGMODE_TRANSP,
380 BGMODE_MAX
381 };
382
383 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
384 {
385 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
386 int32_t size2=size>>1;
387
388 if(newtilebuf[dest_tile].data==NULL)
389 {
390 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
391 }
392
393 int32_t i=0;
394
395 if((dest_tile<<2)+i!=src_quarter1)
396 {
397 for(int32_t j=0; j<8; ++j)
398 {
399 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
400 }
401 }
402
403 i=1;
404
405 if((dest_tile<<2)+i!=src_quarter2)
406 {
407 for(int32_t j=0; j<8; ++j)
408 {
409 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
410 }
411 }
412
413 i=2;
414
415 if((dest_tile<<2)+i!=src_quarter3)
416 {
417 for(int32_t j=0; j<8; ++j)
418 {
419 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
420 }
421 }
422
423 i=3;
424
425 if((dest_tile<<2)+i!=src_quarter4)
426 {
427 for(int32_t j=0; j<8; ++j)
428 {
429 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
430 }
431 }
432 }
433
434 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
435 {
436 al_trace("inside make_combos()\n");
437 int32_t startCombo=0;
438
439 if(!select_combo_2(startCombo,cs))
440 return;
441
442 int32_t temp=combobuf[startCombo].o_tile;
443 combobuf[startCombo].set_tile(startTile);
444
445 if(!edit_combo(startCombo, false, cs))
446 {
447 combobuf[startCombo].set_tile(temp);
448 return;
449 }
450
451 go_combos();
452
453 for(int32_t i=0; i<=endTile-startTile; i++)
454 {
455 combobuf[startCombo+i]=combobuf[startCombo];
456 combobuf[startCombo+i].set_tile(startTile+i);
457 }
458
459 setup_combo_animations();
460 setup_combo_animations2();
461 }
462
463 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
464 {
465 int32_t startCombo=0;
466
467 if(!select_combo_2(startCombo, cs))
468 return;
469
470 int32_t startTile=top*TILES_PER_ROW+left;
471 int32_t temp=combobuf[startCombo].o_tile;
472 combobuf[startCombo].set_tile(startTile);
473
474 if(!edit_combo(startCombo, false, cs))
475 {
476 al_trace("make_combos_rect() early return\n");
477 combobuf[startCombo].set_tile(temp);
478 return;
479 }
480
481 bool smartWrap=false;
482 if(numCols!=4 && numRows>1)
483 {
484 char buf[64];
485 if(numCols<4)
486 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
487 else
488 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
489 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
490 if(ret==1)
491 smartWrap=true;
492 }
493
494 go_combos();
495
496 int32_t combo=startCombo-1;
497 for(int32_t row=0; row<numRows; row++)
498 {
499 for(int32_t col=0; col<numCols; col++)
500 {
501 int32_t tile=startTile+row*TILES_PER_ROW+col;
502 if(smartWrap)
503 // Add 4 per row, and another numRows*4 for every 4 columns
504 // (col&0xFC==col/4*4), and then the column %4
505 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
506 else
507 combo++;
508
509 combobuf[combo]=combobuf[startCombo];
510 combobuf[combo].set_tile(tile);
511 }
512 }
513
514 setup_combo_animations();
515 setup_combo_animations2();
516 }
517
518 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
519
520 static bool nogotiles = false;
521 static bool nogocombos = false;
522
523 void go_tiles()
524 {
525 if(nogotiles) return;
526 last_tile_move_list = nullopt;
527 for(int32_t i=0; i<NEWMAXTILES; ++i)
528 {
529 newundotilebuf[i].format=newtilebuf[i].format;
530
531 if(newundotilebuf[i].data!=NULL)
532 {
533 free(newundotilebuf[i].data);
534 }
535
536 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
537
538 if(newundotilebuf[i].data==NULL)
539 {
540 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
541 }
542
543 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
544 }
545 }
546
547 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
548 {
549 for(int32_t c=0; c<columns; c++)
550 {
551 for(int32_t r=0; r<rows; r++)
552 {
553 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
554 newundotilebuf[t].format=newtilebuf[t].format;
555
556 if(newundotilebuf[t].data!=NULL)
557 {
558 free(newundotilebuf[t].data);
559 }
560
561 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
562
563 if(newundotilebuf[t].data==NULL)
564 {
565 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
566 }
567
568 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
569 }
570 }
571 }
572
573 void comeback_tiles()
574 {
575 if(last_tile_move_list)
576 {
577 last_tile_move_list->undo();
578 last_tile_move_list = nullopt;
579 }
580 for(dword i=0; i<NEWMAXTILES; ++i)
581 {
582 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
583 {
584 newtilebuf[i].format = newundotilebuf[i].format;
585
586 if(newtilebuf[i].data!=NULL)
587 free(newtilebuf[i].data);
588 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
589 if(newtilebuf[i].data==NULL)
590 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
591 }
592
593 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
594 }
595
596 register_blank_tiles();
597 register_used_tiles();
598 }
599
600 void go_combos()
601 {
602 if(nogocombos) return;
603 last_combo_move_list = nullopt;
604
605 undocombobuf = combobuf;
606 }
607
608 void comeback_combos()
609 {
610 if(last_combo_move_list)
611 {
612 last_combo_move_list->undo();
613 last_combo_move_list = nullopt;
614 }
615
616 combobuf = undocombobuf;
617 }
618
619 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
620 {
621 line(dest,x,y,x+s,y+s,c);
622 line(dest,x+s,y,x,y+s,c);
623 }
624 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
625 {
626 line(dest,x,y,x+w,y+h,c);
627 line(dest,x+w,y,x,y+h,c);
628 }
629
630 enum {gm_light, gm_dark, gm_max};
631 int32_t gridmode=gm_light;
632
633 bool has_selection()
634 {
635 for(int32_t i=1; i<17; ++i)
636 {
637 for(int32_t j=1; j<17; ++j)
638 {
639 if(selection_grid[i][j])
640 {
641 return true;
642 }
643 }
644 }
645
646 return false;
647 }
648
649 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
650 {
651 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
652
653 for(int32_t i=1; i<18; ++i)
654 {
655 for(int32_t j=1; j<18; ++j)
656 {
657 // zoomtile16(screen2,tile,79,31,cs,flip,8);
658 if(selection_grid[i-1][j]!=selection_grid[i][j])
659 {
660 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
661 }
662
663 if(selection_grid[i][j-1]!=selection_grid[i][j])
664 {
665 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
666 }
667 }
668 }
669
670 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
671 // selection_anchor=(selection_anchor+1)%64;
672 }
673
674 bool is_selecting()
675 {
676 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
677 }
678
679 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
680 {
681 int32_t x1=zc_min(selecting_x1,selecting_x2);
682 int32_t x2=zc_max(selecting_x1,selecting_x2);
683 int32_t y1=zc_min(selecting_y1,selecting_y2);
684 int32_t y2=zc_max(selecting_y1,selecting_y2);
685
686 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
687 for(int32_t i=1; i<18; ++i)
688 {
689 for(int32_t j=1; j<18; ++j)
690 {
691 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
692
693 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
694 {
695 if(selection_grid[i-1][j]!=selection_grid[i][j])
696 {
697 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
698 }
699
700 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
701 }
702
703 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
704 {
705 if(selection_grid[i][j-1]!=selection_grid[i][j])
706 {
707 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
708 }
709
710 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
711 }
712 }
713 }
714
715 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
716 // selection_anchor=(selection_anchor+1)%64;
717 }
718
719 void unfloat_selection();
720 bool floating_sel = false;
721 byte floatsel[256];
722 byte undofloatsel[256];
723 bool undo_is_floatsel = false;
724
725
726 void add_color_to_selection(int32_t color)
727 {
728 unfloat_selection();
729 for(int32_t i=1; i<17; ++i)
730 {
731 for(int32_t j=1; j<17; ++j)
732 {
733 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
734 {
735 selection_grid[i][j]=1;
736 }
737 }
738 }
739 }
740
741 void remove_color_from_selection(int32_t color)
742 {
743 unfloat_selection();
744 for(int32_t i=1; i<17; ++i)
745 {
746 for(int32_t j=1; j<17; ++j)
747 {
748 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
749 {
750 selection_grid[i][j]=0;
751 }
752 }
753 }
754 }
755
756 void intersect_color_with_selection(int32_t color)
757 {
758 unfloat_selection();
759 for(int32_t i=1; i<17; ++i)
760 {
761 for(int32_t j=1; j<17; ++j)
762 {
763 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
764 {
765 selection_grid[i][j]=1;
766 }
767 else
768 {
769 selection_grid[i][j]=0;
770 }
771 }
772 }
773 }
774
775 bool is_in_selection(int32_t x, int32_t y)
776 {
777 x %= 16; y %= 16;
778 if(x < 0) x = (16 - abs(x));
779 if(y < 0) y = (16 - abs(y));
780 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
781 }
782
783 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
784 {
785 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
786 int gridcol = gridmode==gm_light?vc(7):vc(8);
787
788 cset <<= 4;
789 if(newtilebuf[tile].format>tf4Bit)
790 cset=0;
791
792 int g = hide_grid ? 1 : 0;
793 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
794 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
795
796 unpack_tile(newtilebuf, tile, 0, false);
797 byte *si = unpackbuf;
798 for(int32_t cy=0; cy<16; cy++)
799 {
800 for(int32_t cx=0; cx<16; cx++)
801 {
802 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
803 int32_t dx = ((flip&1)?15-cx:cx)*m;
804 int32_t dy = ((flip&2)?15-cy:cy)*m;
805 if(col)
806 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
807
808 if(!col && xmode == XMODE_X)
809 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
810
811 ++si;
812 }
813 }
814
815 if(!hide_grid)
816 {
817 for(int cx = 0; cx <= 16; ++cx)
818 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
819 for(int cy = 0; cy <= 16; ++cy)
820 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
821 }
822
823 if(show_quartgrid)
824 {
825 int offs = (8*m);
826 const int RAD = 3;
827 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
828 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
829 }
830
831 if(has_selection()||is_selecting())
832 {
833 selection_anchor=(selection_anchor+1)%64;
834
835 if(has_selection()||is_selecting())
836 draw_selection_outline(dest, x, y, m);
837
838 if(is_selecting())
839 draw_selecting_outline(dest, x, y, m);
840 }
841 }
842
843 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
844 {
845 if(!jwin)
846 {
847 if(flags&D_SELECTED)
848 {
849 zc_swap(fg,bg);
850 }
851
852 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
853 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
854 rect(dest,x,y,x+w-2,y+h-2,fg);
855 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
856 }
857 else
858 {
859 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
860 }
861 }
862
863 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
864 {
865 if(!jwin)
866 {
867 if(flags&D_SELECTED)
868 {
869 zc_swap(fg,bg);
870 }
871
872 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
873 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
874 rect(dest,x,y,x+w-2,y+h-2,fg);
875 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
876 }
877 else
878 {
879 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
880 }
881 }
882
883 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
884 {
885 if(flags&D_SELECTED)
886 {
887 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
888 ++x;
889 ++y;
890 --w;
891 --h;
892 }
893 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
894 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
895
896 //Forcibly fit the text within the button
897 char buf[512] = {0};
898 strcpy(buf, text);
899
900 bool dis = (flags&D_DISABLED);
901 auto hei = text_height(font);
902 auto len = text_length(font,buf);
903 auto borderwid = 8;
904 if(len > w - borderwid + (dis ? 1 : 0))
905 {
906 auto ind = strlen(buf) - 1;
907 auto dotcount = 0;
908 while(len > w - borderwid + (dis ? 1 : 0))
909 {
910 if(dotcount >= 2)
911 buf[ind+2] = 0;
912 else ++dotcount;
913 buf[ind--] = '.';
914 len = text_length(font,buf);
915 }
916 }
917 if(dis)
918 {
919 ++len; ++hei;
920 }
921 BITMAP* tmp = create_bitmap_ex(8,len,hei);
922 clear_bitmap(tmp);
923 if(dis)
924 {
925 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
926 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
927 }
928 else
929 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
930 auto tx = x+((w-len)/2);
931 auto ty = y+((h-hei)/2);
932 if(len > w-borderwid)
933 {
934 tx = x+borderwid/2;
935 len = w-borderwid;
936 }
937 if(hei > h-borderwid)
938 {
939 ty = y+borderwid/2;
940 hei = h-borderwid;
941 }
942 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
943 destroy_bitmap(tmp);
944 }
945
946 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
947 {
948 bool over=false;
949
950 while(gui_mouse_b())
951 {
952 //vsync();
953 if(mouse_in_rect(x,y,w,h))
954 {
955 if(!over)
956 {
957 vsync();
958 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
959 over=true;
960
961 update_hw_screen();
962 }
963 }
964 else
965 {
966 if(over)
967 {
968 vsync();
969 draw_layer_button(screen, x, y, w, h, text, flags);
970 over=false;
971
972 update_hw_screen();
973 }
974 }
975 rest(1);
976 }
977
978 if(over)
979 {
980 vsync();
981 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
982
983 update_hw_screen();
984 }
985
986 return over;
987 }
988
989 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
990 {
991 bool over=false;
992
993 while(gui_mouse_b())
994 {
995 custom_vsync();
996
997 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
998 {
999 if(!over)
1000 {
1001 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1002 over=true;
1003 }
1004 }
1005 else
1006 {
1007 if(over)
1008 {
1009 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1010 over=false;
1011 }
1012 }
1013 }
1014
1015 if(over)
1016 {
1017 custom_vsync();
1018 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1019 }
1020
1021 return over;
1022 }
1023
1024 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1025 {
1026 if(!jwin)
1027 {
1028 if(flags&D_SELECTED)
1029 {
1030 zc_swap(fg,bg);
1031 }
1032
1033 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1034 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1035 rect(dest,x,y,x+w-2,y+h-2,fg);
1036 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1037
1038 if(overlay)
1039 {
1040 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1041 }
1042 else
1043 {
1044 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1045 }
1046 }
1047 else
1048 {
1049 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1050 }
1051 }
1052
1053 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1054 {
1055 bool over=false;
1056
1057 while(gui_mouse_b())
1058 {
1059 custom_vsync();
1060
1061 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1062 {
1063 if(!over)
1064 {
1065 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1066 over=true;
1067 }
1068 }
1069 else
1070 {
1071 if(over)
1072 {
1073 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1074 over=false;
1075 }
1076 }
1077 }
1078
1079 return over;
1080 }
1081
1082 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1083 {
1084 bool over=false;
1085
1086 while(gui_mouse_b())
1087 {
1088 custom_vsync();
1089
1090 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1091 {
1092 if(!over)
1093 {
1094 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1095 over=true;
1096 }
1097 }
1098 else
1099 {
1100 if(over)
1101 {
1102 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1103 over=false;
1104 }
1105 }
1106 }
1107
1108 if(over)
1109 {
1110 custom_vsync();
1111 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1112 }
1113
1114 return over;
1115 }
1116 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1117 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1118
1119 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1120 {
1121 //these are here to bypass compiler warnings about unused arguments
1122 bg=bg;
1123 fg=fg;
1124
1125 int32_t r, center;
1126
1127 for(int32_t k=0; k<7; k++)
1128 {
1129 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1130 {
1131 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1132 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1133 //*
1134 r = 9/2;
1135
1136 center = x+(k*25)+r;
1137 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1138
1139 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1140 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1141 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1142 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1143 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1144
1145 if(value==k)
1146 {
1147 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1148 }
1149
1150 //*/
1151 }
1152 }
1153 }
1154
1155 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1156 {
1157 while(gui_mouse_b())
1158 {
1159 custom_vsync();
1160
1161 for(int32_t k=0; k<7; k++)
1162 {
1163 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1164 {
1165 //if on radio button
1166 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1167 {
1168 value=k;
1169 draw_layerradio(dest,x,y,bg,fg,value);
1170 refresh(rMENU);
1171 }
1172 }
1173 }
1174 }
1175 }
1176
1177 //*************** tile flood fill stuff **************
1178
1179 byte tf_c;
1180 byte tf_u;
1181
1182 void tile_floodfill_rec(int32_t x,int32_t y)
1183 {
1184 if(is_in_selection(x,y))
1185 {
1186 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1187 --x;
1188
1189 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1190 {
1191 if(is_in_selection(x,y))
1192 {
1193 unpackbuf[(y<<4)+x] = tf_c;
1194 }
1195
1196 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1197 tile_floodfill_rec(x,y-1);
1198
1199 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1200 tile_floodfill_rec(x,y+1);
1201
1202 ++x;
1203 }
1204 }
1205 }
1206
1207 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1208 {
1209 if(is_in_selection(x,y))
1210 {
1211 if(floating_sel)
1212 {
1213 memcpy(unpackbuf, floatsel, 256);
1214 }
1215 else unpack_tile(newtilebuf, tile, 0, false);
1216 tf_c = c;
1217 tf_u = unpackbuf[(y<<4)+x];
1218
1219 if(tf_u != tf_c)
1220 tile_floodfill_rec(x,y);
1221 if(floating_sel)
1222 {
1223 memcpy(floatsel, unpackbuf, 256);
1224 }
1225 else pack_tile(newtilebuf,unpackbuf,tile);
1226 }
1227 }
1228
1229 //***************** tile editor stuff *****************
1230 9 size_and_pos ok_button(302,562,71,21);
1231 9 size_and_pos cancel_button(376,562,71,21);
1232 9 size_and_pos edit_button(550,562,86,21);
1233 9 size_and_pos hlcbox(742,392,16,16);
1234 9 size_and_pos hov_prev(742,338,50,50);
1235 9 size_and_pos cpalette_4(648,416,4,4,64,64);
1236 9 size_and_pos cpalette_8(648,416,16,14,16,18);
1237 9 size_and_pos fg_prev(648,316,50,50);
1238 9 size_and_pos bg_prev(648+30,316+30,50,50);
1239 9 size_and_pos zoomtile(124,32,16,16,32,32);
1240 9 size_and_pos prev_til_1(648,31,96,96);
1241 9 size_and_pos prev_til_2(752,31,96,96);
1242 9 size_and_pos prev_til_3(648,135,96,96);
1243 9 size_and_pos prev_til_4(752,135,96,96);
1244 9 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1245 9 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1246 9 size_and_pos color_info(4,189,1,1,116,8);
1247 9 size_and_pos color_info_btn(24,189,96,21);
1248 9 size_and_pos tool_btns(22,29,2,4,39,39);
1249 9 size_and_pos x_btn(890,5,15,13);
1250 9 size_and_pos info_btn(872,5,15,13);
1251 9 size_and_pos hidegrid_cbox(124,552,16,16);
1252 9 size_and_pos quartgrid_cbox(124,572,16,16);
1253 9 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1254 9 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1255 9 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1256
1257 int32_t c1=1;
1258 int32_t c2=0;
1259 int32_t floating_tile = -1;
1260 int32_t tool = t_pen;
1261 int32_t old_tool = -1;
1262 int32_t tool_cur = -1;
1263 int32_t select_mode = 0;
1264 int32_t drawing=0;
1265
1266 bool qgrid_tool(int tool)
1267 {
1268 switch(tool)
1269 {
1270 case t_pen:
1271 case t_fill:
1272 case t_recolor:
1273 case t_wand:
1274 return true;
1275 }
1276 return false;
1277 }
1278
1279 void set_tool_sprite(int tool, int type)
1280 {
1281 int spr = ZQM_NORMAL;
1282 switch(tool)
1283 {
1284 case t_pen: spr = ZQM_SWORD; break;
1285 case t_fill: spr = ZQM_POTION; break;
1286 case t_recolor: spr = ZQM_WAND; break;
1287 case t_eyedropper: spr = ZQM_LENS; break;
1288 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1289 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1290 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1291 }
1292 MouseSprite::set(spr);
1293 }
1294 void update_tool_cursor()
1295 {
1296 int32_t temp_mouse_x=gui_mouse_x();
1297 int32_t temp_mouse_y=gui_mouse_y();
1298
1299 int32_t type=0;
1300
1301 if(has_selection())
1302 {
1303 switch(tool)
1304 {
1305 case t_select:
1306 case t_wand:
1307 type+=select_mode;
1308 break;
1309 }
1310 }
1311
1312 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1313 {
1314 if(tool_cur==-1)
1315 set_tool_sprite(tool,type);
1316
1317 tool_cur=tool;
1318 }
1319 else if(tool_cur != -1)
1320 {
1321 MouseSprite::set(ZQM_NORMAL);
1322 tool_cur = -1;
1323 }
1324 }
1325
1326 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile, bool create_tbar)
1327 {
1328 PALETTE tpal;
1329 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1330 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1331 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1332
1333 if(!create_tbar)
1334 {
1335 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1336 }
1337 else
1338 {
1339 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1340 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1341 }
1342
1343 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1344
1345 clear_to_color(preview_bmp, 0);
1346
1347 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1348 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1349 puttile16(preview_bmp,tile,0,0,cs,flip);
1350 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1351
1352 clear_to_color(preview_bmp, 0);
1353 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1354 overtile16(preview_bmp,tile,0,0,cs,flip);
1355 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1356 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1357
1358 unpack_tile(newtilebuf, tile, 0, true);
1359 if(floating_sel)
1360 for(auto q = 0; q < 256; ++q)
1361 if(floatsel[q])
1362 unpackbuf[q] = floatsel[q];
1363 byte tmptile[256];
1364 byte *tmpptr = tmptile;
1365 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1366 pack_tile(newtilebuf,unpackbuf,tile);
1367 clear_to_color(preview_bmp, 0);
1368
1369 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1370 puttile16(preview_bmp,tile,0,0,cs,flip);
1371 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1372
1373 clear_to_color(preview_bmp, 0);
1374 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1375 overtile16(preview_bmp,tile,0,0,cs,flip);
1376 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1377
1378 //Color info
1379 {
1380 auto fh = color_info.yscale = text_height(font);
1381 int y = color_info.y;
1382 int rx = color_info.x+color_info.xscale;
1383 color_info.h = 1;
1384 if(showcolortip)
1385 {
1386 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1387 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1388 auto str = get_tile_colornames(tile,cs);
1389 size_t pos = 0;
1390 char buf[512] = {0};
1391 char cbuf[16] = {0};
1392 while(pos < str.size())
1393 {
1394 y += fh;
1395 if(y+fh > zq_screen_h)
1396 break; //Out of space!
1397 auto endpos = str.find_first_of('\n',pos);
1398
1399 if(endpos == std::string::npos)
1400 {
1401 strcpy(buf,str.substr(pos).c_str());
1402 pos = str.size();
1403 }
1404 else
1405 {
1406 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1407 pos = endpos+1;
1408 }
1409 //Ensure the name fits horizontally
1410 if(text_length(font,buf) > color_info.xscale)
1411 {
1412 size_t pos = 0;
1413 for(; buf[pos]; ++pos)
1414 {
1415 if(buf[pos] == ':')
1416 {
1417 strcpy(cbuf, buf+pos);
1418 buf[pos] = 0;
1419 break;
1420 }
1421 }
1422 size_t clen = text_length(font,cbuf);
1423 size_t dotlen = text_length(font,"..");
1424
1425 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1426 buf[--pos] = 0;
1427 while(buf[pos] == ' ')
1428 buf[pos] = 0;
1429 strcat(buf,"..");
1430 strcat(buf,cbuf);
1431 }
1432 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1433 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1434 ++color_info.h;
1435 }
1436 jwin_draw_frame(screen2,color_info.x-2,color_info.y-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1437 }
1438 else
1439 {
1440 draw_text_button(screen2,color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,
1441 "Show Colors",vc(1),vc(14),0,true);
1442 }
1443 }
1444
1445 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1446
1447 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1448 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1449
1450 if(floating_sel)
1451 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1452 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1453 if(newtilebuf[tile].format==tf8Bit)
1454 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1455 else
1456 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1457
1458 PALETTE temppal;
1459
1460 //palette and mouse
1461 switch(newtilebuf[tile].format)
1462 {
1463 case tf4Bit:
1464 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1465 get_palette(temppal);
1466
1467 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1468 {
1469 size_and_pos const& s = cpalette_4.subsquare(i);
1470 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1471 }
1472
1473 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1474 break;
1475
1476 case tf8Bit:
1477 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1478
1479 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1480 {
1481 size_and_pos const& s = cpalette_8.subsquare(i);
1482 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1483 }
1484
1485 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1486 break;
1487 }
1488
1489 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1490 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1491 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1492
1493 if(c2==0)
1494 {
1495 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1496 }
1497
1498 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1499 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1500 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1501
1502 if(c1==0)
1503 {
1504 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1505 }
1506
1507 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1508 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1509 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1510 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1511 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1512
1513 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1514 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1515
1516 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1517 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1518
1519 bool qgrd = show_quartgrid && qgrid_tool(tool);
1520 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1521 for(int q = 0; q < REFL_MAX; ++q)
1522 {
1523 auto& sqr = reflbtn_grid.subsquare(q);
1524 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1525 }
1526 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1527 for(int q = 0; q < XMODE_MAX; ++q)
1528 {
1529 auto& sqr = xmodebtn_grid.subsquare(q);
1530 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1531 }
1532 for(int q = 0; q < BGMODE_MAX; ++q)
1533 {
1534 auto& sqr = bgmodebtn_grid.subsquare(q);
1535 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1536 }
1537
1538 //tool buttons
1539 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1540 {
1541 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1542 int col = toolbtn%tool_btns.w;
1543 int row = toolbtn/tool_btns.w;
1544
1545 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1546 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1547 }
1548
1549 //coordinates
1550 {
1551 auto mx = gui_mouse_x();
1552 auto my = gui_mouse_y();
1553 int32_t ind = zoomtile.rectind(mx,my);
1554 int32_t temp_x=ind%zoomtile.w;
1555 int32_t temp_y=ind/zoomtile.w;
1556 int color = -1;
1557
1558 bool is8b = newtilebuf[tile].format > tf4Bit;
1559 if(ind > -1)
1560 {
1561 char xbuf[16];
1562 sprintf(xbuf, "x: %d", temp_x);
1563 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1564 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1565 unpack_tile(newtilebuf, tile, 0, false);
1566 byte *si = unpackbuf;
1567 si+=ind;
1568 color = *si;
1569 }
1570 else if(fg_prev.rect(mx,my))
1571 color = c1;
1572 else if(bg_prev.rect(mx,my))
1573 color = c2;
1574 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1575 if(color > -1)
1576 {
1577 get_palette(tpal);
1578 char separator = ' ';
1579 char buf[512] = {0};
1580
1581 int realcol = color+(is8b?0:CSET(cs));
1582 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1583 auto& c = tpal[realcol];
1584
1585 if(tthighlight)
1586 {
1587 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1588 size_and_pos const& csqr = mainsqr.subsquare(color);
1589
1590 int hlcol = getHighlightColor(tpal[realcol]);
1591 int hlthick = 4;
1592 int extraborder = is8b ? 8 : 0;
1593 int borderthick = hlthick+extraborder;
1594
1595 if(is8b)
1596 {
1597 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1598 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1599 }
1600 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1601 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1602 if(xcolor)
1603 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1604 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1605 }
1606
1607 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1608 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1609
1610 strcpy(buf, get_color_name(realcol, is8b).c_str());
1611 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1612
1613 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1614 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1615
1616 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1617 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1618 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1619 if(xcolor)
1620 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1621 }
1622 }
1623
1624 custom_vsync();
1625 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1626 update_tool_cursor();
1627 SCRFIX();
1628 }
1629
1630 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1631 {
1632 unfloat_selection();
1633 if(tile>tile2)
1634 {
1635 zc_swap(tile, tile2);
1636 }
1637
1638 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1639 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1640
1641 int32_t start=tile;
1642 int32_t end=tile2;
1643
1644 // Might have top-right and bottom-left corners selected...
1645 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1646 {
1647 start=tile-(TILECOL(tile)-TILECOL(tile2));
1648 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1649 }
1650
1651 for(int32_t temptile=start; temptile<=end; temptile++)
1652 {
1653 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1654 {
1655 unpack_tile(newtilebuf, temptile, 0, true);
1656
1657 if(flip&1)
1658 {
1659 for(int32_t y=0; y<16; y++)
1660 {
1661 for(int32_t x=0; x<8; x++)
1662 {
1663 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1664 }
1665 }
1666 }
1667
1668 if(flip&2)
1669 {
1670 for(int32_t y=0; y<8; y++)
1671 {
1672 for(int32_t x=0; x<16; x++)
1673 {
1674 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1675 }
1676 }
1677 }
1678
1679 pack_tile(newtilebuf,unpackbuf,temptile);
1680 }
1681 }
1682 }
1683
1684 void rotate_tile(int32_t tile, bool backward)
1685 {
1686 unfloat_selection();
1687 unpack_tile(newtilebuf, tile, 0, true);
1688 byte tempunpackbuf[256];
1689 byte tempx, tempy;
1690
1691 for(tempx=0; tempx<16; tempx++)
1692 {
1693 for(tempy=0; tempy<16; tempy++)
1694 {
1695 if(!backward)
1696 {
1697 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1698 }
1699 else
1700 {
1701 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1702 }
1703 }
1704 }
1705
1706 pack_tile(newtilebuf,tempunpackbuf,tile);
1707 }
1708
1709 static int32_t undocount=128;
1710 byte undotile[256];
1711
1712 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1713 {
1714 byte buf[256];
1715
1716 for(int32_t i=0; i<undocount; i++)
1717 {
1718 newtilebuf[tile].data[i]=undotile[i];
1719 }
1720
1721 if(!(horizontal||vertical))
1722 {
1723 return;
1724 }
1725
1726 unpack_tile(newtilebuf, tile, 0, true);
1727
1728 for(int32_t i=0; i<256; i++)
1729 {
1730 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1731 buf[shift_ind] = unpackbuf[i];
1732 }
1733
1734 if(clear)
1735 {
1736 for(int32_t r=0; r<abs(vertical); r++)
1737 {
1738 for(int32_t c=0; c<16; c++)
1739 {
1740 buf[(vertical>0?r:15-r)*16+c]=0;
1741 }
1742 }
1743
1744 for(int32_t r=0; r<16; r++)
1745 {
1746 for(int32_t c=0; c<abs(horizontal); c++)
1747 {
1748 buf[r*16+(horizontal>0?c:15-c)]=0;
1749 }
1750 }
1751 }
1752
1753 pack_tile(newtilebuf,buf,tile);
1754 }
1755
1756 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1757 {
1758 byte buf[256];
1759
1760 if(!(horizontal||vertical))
1761 {
1762 return;
1763 }
1764
1765 memset(buf,0,256);
1766
1767 for(int32_t i=0; i<256; i++)
1768 {
1769 if(is_in_selection(i%16,i/16))
1770 {
1771 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1772 buf[shift_ind] = floatsel[i];
1773 }
1774 }
1775
1776 memcpy(floatsel,buf,256);
1777 }
1778
1779 void float_selection(int32_t tile, bool clear)
1780 {
1781 if(floating_sel) return;
1782 floating_sel = true;
1783 floating_tile = tile;
1784
1785 unpack_tile(newtilebuf, tile, 0, true);
1786
1787 for(auto q = 0; q < 256; ++q)
1788 {
1789 if(is_in_selection(q%16,q/16))
1790 {
1791 floatsel[q] = unpackbuf[q];
1792 unpackbuf[q] = clear ? 0 : c2;
1793 }
1794 else floatsel[q] = 0;
1795 }
1796
1797 pack_tile(newtilebuf,unpackbuf,tile);
1798 }
1799
1800 void unfloat_selection()
1801 {
1802 if(!floating_sel) return;
1803 floating_sel = false;
1804
1805 unpack_tile(newtilebuf, floating_tile, 0, true);
1806
1807 for(auto q = 0; q < 256; ++q)
1808 {
1809 if(floatsel[q])
1810 {
1811 unpackbuf[q] = floatsel[q];
1812 }
1813 }
1814
1815 pack_tile(newtilebuf,unpackbuf,floating_tile);
1816 floating_tile = -1;
1817 }
1818
1819 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1820 {
1821 if(floating_sel)
1822 {
1823 for(auto q = 0; q < 256; ++q)
1824 {
1825 if(ignore_transparent && floatsel[q]==0)
1826 continue;
1827 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1828 }
1829 return;
1830 }
1831
1832 byte buf[256];
1833 unpack_tile(newtilebuf, tile, 0, true);
1834
1835 for(int32_t i=0; i<256; i++)
1836 {
1837 buf[i]=unpackbuf[i];
1838
1839 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1840 continue;
1841
1842 if(ignore_transparent)
1843 {
1844 if(buf[i]==0)
1845 continue;
1846
1847 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1848 }
1849 else // Don't ignore transparent
1850 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1851 }
1852
1853 pack_tile(newtilebuf,buf,tile);
1854 }
1855
1856 void clear_selection_grid()
1857 {
1858 unfloat_selection();
1859 for(int32_t x=0; x<18; ++x)
1860 {
1861 for(int32_t y=0; y<18; ++y)
1862 {
1863 selection_grid[x][y]=0;
1864 }
1865 }
1866 }
1867
1868 void invert_selection_grid()
1869 {
1870 unfloat_selection();
1871 for(int32_t x=1; x<17; ++x)
1872 {
1873 for(int32_t y=1; y<17; ++y)
1874 {
1875 selection_grid[x][y]=selection_grid[x][y]?0:1;
1876 }
1877 }
1878 }
1879
1880 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1881 {
1882 byte local_grid[16][16];
1883 memset(local_grid, 0, sizeof(local_grid));
1884 for(auto x = 0; x < 16; ++x)
1885 {
1886 for(auto y = 0; y < 16; ++y)
1887 {
1888 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1889 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1890 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1891 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1892 }
1893 }
1894 for(auto x = 0; x < 16; ++x)
1895 {
1896 for(auto y = 0; y < 16; ++y)
1897 {
1898 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1899 }
1900 }
1901 }
1902
1903 void show_edit_tile_help()
1904 {
1905 InfoDialog("Help: Tile Editor", "Hotkeys:"
1906 "\nF1: This Help Dialog"
1907 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1908 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1909 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1910 "\nH/V: Flip | (Shift+)R: Rotate"
1911 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1912 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1913 "\nF12: Screenshot (whole screen)"
1914 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1915 "\nWhen not on Select tools, hold to swap:"
1916 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1917 }
1918
1919 static int move_origin_x=-1, move_origin_y=-1;
1920 static int prev_x=-1, prev_y=-1;
1921 bool __pixel_draw(int x, int y, int tile, int flip)
1922 {
1923 bool ret = false;
1924 switch(tool)
1925 {
1926 case t_pen:
1927 if(flip&1) x=15-x;
1928
1929 if(flip&2) y=15-y;
1930
1931 if(is_in_selection(x,y))
1932 {
1933 if(floating_sel)
1934 {
1935 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1936 }
1937 else
1938 {
1939 unpack_tile(newtilebuf, tile, 0, false);
1940 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1941 pack_tile(newtilebuf, unpackbuf,tile);
1942 }
1943 }
1944 break;
1945
1946 case t_fill:
1947 if(is_in_selection(x,y))
1948 {
1949 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1950 ret = true;
1951 }
1952 break;
1953
1954 case t_recolor:
1955 if(is_in_selection(x,y))
1956 {
1957 if(floating_sel)
1958 {
1959 tf_u = floatsel[(y<<4)+x];
1960 for(int32_t i=0; i<256; i++)
1961 {
1962 if(is_in_selection(i&15,i>>4))
1963 {
1964 if(floatsel[i]==tf_u)
1965 {
1966 floatsel[i]=(drawing==1)?c1:c2;
1967 }
1968 }
1969 }
1970 }
1971 else
1972 {
1973 unpack_tile(newtilebuf, tile, 0, false);
1974 tf_u = unpackbuf[(y<<4)+x];
1975 if(tf_u != ((drawing==1)?c1:c2))
1976 {
1977 for(int32_t i=0; i<256; i++)
1978 {
1979 if(is_in_selection(i&15,i>>4))
1980 {
1981 if(unpackbuf[i]==tf_u)
1982 {
1983 unpackbuf[i]=(drawing==1)?c1:c2;
1984 }
1985 }
1986 }
1987
1988 pack_tile(newtilebuf, unpackbuf,tile);
1989 }
1990 }
1991 ret = true;
1992 }
1993 break;
1994
1995 case t_eyedropper:
1996 if(floating_sel)
1997 memcpy(unpackbuf, floatsel, 256);
1998 else unpack_tile(newtilebuf, tile, 0, false);
1999
2000 if(gui_mouse_b()&1)
2001 {
2002 c1=unpackbuf[((y<<4)+x)];
2003 }
2004
2005 if(gui_mouse_b()&2)
2006 {
2007 c2=unpackbuf[((y<<4)+x)];
2008 }
2009 break;
2010
2011 case t_move:
2012 if((prev_x!=x)||(prev_y!=y))
2013 {
2014 if(has_selection())
2015 {
2016 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2017 wrap_sel_tile(y-prev_y, x-prev_x);
2018 shift_selection_grid(x-prev_x, y-prev_y);
2019 }
2020 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2021 prev_x=x;
2022 prev_y=y;
2023 }
2024 break;
2025
2026 case t_select:
2027 unfloat_selection();
2028 if(flip&1) x=15-x;
2029
2030 if(flip&2) y=15-y;
2031
2032 if(selecting_x1==-1||selecting_y1==-1)
2033 {
2034 selecting_x1=x;
2035 selecting_y1=y;
2036 }
2037 else
2038 {
2039 selecting_x2=x;
2040 selecting_y2=y;
2041 }
2042 break;
2043
2044 case t_wand:
2045 unfloat_selection();
2046 if(flip&1) x=15-x;
2047
2048 if(flip&2) y=15-y;
2049
2050 switch(select_mode)
2051 {
2052 case 0:
2053 clear_selection_grid();
2054 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2055 break;
2056
2057 case 1:
2058 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2059 break;
2060
2061 case 2:
2062 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2063 break;
2064
2065 case 3:
2066 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2067 break;
2068 }
2069
2070 ret = true;
2071 break;
2072 }
2073 return ret;
2074 }
2075 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2076 {
2077 popup_zqdialog_start();
2078 FONT* oldfont = font;
2079 font = get_custom_font(CFONT_DLG);
2080 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2081 status_info.yscale = text_height(font);
2082 status_info.y = 308-(status_info.h*status_info.yscale);
2083 hover_info.yscale = status_info.yscale;
2084 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2085 go();
2086 undocount = tilesize(newtilebuf[tile].format);
2087 clear_selection_grid();
2088 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2089
2090 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2091 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2092
2093 PALETTE tpal;
2094 byte oldtile[256];
2095
2096 memset(&tpal, 0, sizeof(PALETTE));
2097 memset(oldtile, 0, 256);
2098
2099 for(int32_t i=0; i<undocount; i++)
2100 {
2101 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2102 }
2103 byte undoselgrid[16][16];
2104 for(auto x = 0; x < 16; ++x)
2105 for(auto y = 0; y < 16; ++y)
2106 undoselgrid[x][y] = selection_grid[x+1][y+1];
2107 for(auto q = 0; q < 256; ++q)
2108 {
2109 floatsel[q] = 0;
2110 undofloatsel[q] = 0;
2111 floating_sel = false;
2112 undo_is_floatsel = false;
2113 }
2114
2115 int32_t tile_x=-1, tile_y=-1;
2116 int32_t temp_x=-1, temp_y=-1;
2117 bool bdown=false;
2118 int32_t done=0;
2119 drawing=0;
2120 tool_cur = -1;
2121
2122 get_palette(tpal);
2123
2124 if(newtilebuf[tile].format==tf4Bit)
2125 {
2126 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2127 }
2128 else
2129 {
2130 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2131 }
2132
2133 custom_vsync();
2134 zc_set_palette(tpal);
2135 draw_edit_scr(tile,flip,cs,oldtile, true);
2136
2137 while(gui_mouse_b())
2138 {
2139 /* do nothing */
2140 rest(1);
2141 }
2142
2143 move_origin_x=-1;
2144 move_origin_y=-1;
2145 prev_x=-1;
2146 prev_y=-1;
2147
2148
2149
2150 byte selection_pattern_source[8][8]=
2151 {
2152 {1, 1, 1, 1, 0, 0, 0, 0},
2153 {1, 1, 1, 0, 0, 0, 0, 1},
2154 {1, 1, 0, 0, 0, 0, 1, 1},
2155 {1, 0, 0, 0, 0, 1, 1, 1},
2156 {0, 0, 0, 0, 1, 1, 1, 1},
2157 {0, 0, 0, 1, 1, 1, 1, 0},
2158 {0, 0, 1, 1, 1, 1, 0, 0},
2159 {0, 1, 1, 1, 1, 0, 0, 0},
2160 };
2161
2162 byte selecting_pattern_source[8][8]=
2163 {
2164 {1, 1, 0, 0, 0, 0, 1, 1},
2165 {1, 0, 0, 0, 0, 1, 1, 1},
2166 {0, 0, 0, 0, 1, 1, 1, 1},
2167 {0, 0, 0, 1, 1, 1, 1, 0},
2168 {0, 0, 1, 1, 1, 1, 0, 0},
2169 {0, 1, 1, 1, 1, 0, 0, 0},
2170 {1, 1, 1, 1, 0, 0, 0, 0},
2171 {1, 1, 1, 0, 0, 0, 0, 1},
2172 };
2173
2174 byte intersection_pattern_source[8][8]=
2175 {
2176 {0, 0, 1, 1, 0, 0, 1, 1},
2177 {0, 1, 1, 0, 0, 1, 1, 0},
2178 {1, 1, 0, 0, 1, 1, 0, 0},
2179 {1, 0, 0, 1, 1, 0, 0, 1},
2180 {0, 0, 1, 1, 0, 0, 1, 1},
2181 {0, 1, 1, 0, 0, 1, 1, 0},
2182 {1, 1, 0, 0, 1, 1, 0, 0},
2183 {1, 0, 0, 1, 1, 0, 0, 1},
2184 };
2185
2186 selection_pattern=create_bitmap_ex(8, 8, 8);
2187
2188 for(int32_t x=0; x<8; ++x)
2189 {
2190 for(int32_t y=0; y<8; ++y)
2191 {
2192 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2193 }
2194 }
2195
2196 selecting_pattern=create_bitmap_ex(8, 8, 8);
2197
2198 for(int32_t x=0; x<8; ++x)
2199 {
2200 for(int32_t y=0; y<8; ++y)
2201 {
2202 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2203 }
2204 }
2205
2206 intersection_pattern=create_bitmap_ex(8, 8, 8);
2207
2208 for(int32_t x=0; x<8; ++x)
2209 {
2210 for(int32_t y=0; y<8; ++y)
2211 {
2212 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2213 }
2214 }
2215
2216 do
2217 {
2218 HANDLE_CLOSE_ZQDLG();
2219 if(exiting_program) break;
2220 int32_t temp_mouse_x=gui_mouse_x();
2221 int32_t temp_mouse_y=gui_mouse_y();
2222 rest(4);
2223 bool redraw=false;
2224 bool did_wand_select=false;
2225
2226 if(keypressed())
2227 {
2228 bool ctrl = CHECK_CTRL_CMD;
2229 int k = readkey()>>8;
2230 switch(k)
2231 {
2232 case KEY_F1:
2233 show_edit_tile_help();
2234 break;
2235 case KEY_ENTER_PAD:
2236 case KEY_ENTER:
2237 if(floating_sel)
2238 unfloat_selection();
2239 else done=2;
2240 break;
2241
2242 case KEY_ESC:
2243 if(floating_sel)
2244 unfloat_selection();
2245 else if(has_selection())
2246 clear_selection_grid();
2247 else done=1;
2248 break;
2249
2250 case KEY_DEL:
2251 {
2252 unpack_tile(newtilebuf, tile, 0, false);
2253 bool all = CHECK_CTRL_CMD || !has_selection();
2254 bool canDel = false;
2255 if(all)
2256 {
2257 //Check all
2258 for(auto q = 0; q < 256; ++q)
2259 if(unpackbuf[q])
2260 {
2261 canDel = true;
2262 break;
2263 }
2264 }
2265 else
2266 {
2267 //Check selection
2268 for(auto x = 0; x < 16; ++x)
2269 for(auto y = 0; y < 16; ++y)
2270 if(is_in_selection(x,y))
2271 if(unpackbuf[(y<<4)+x])
2272 {
2273 canDel = true;
2274 break;
2275 }
2276 }
2277 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2278
2279 for(int32_t i=0; i<undocount; i++)
2280 {
2281 undotile[i]=newtilebuf[tile].data[i];
2282 }
2283 for(auto x = 0; x < 16; ++x)
2284 for(auto y = 0; y < 16; ++y)
2285 undoselgrid[x][y] = selection_grid[x+1][y+1];
2286 for(auto q = 0; q < 256; ++q)
2287 undofloatsel[q] = floatsel[q];
2288 undo_is_floatsel = floating_sel;
2289
2290 if(CHECK_CTRL_CMD || !has_selection())
2291 {
2292 //Delete all
2293 for(auto q = 0; q < 256; ++q)
2294 {
2295 unpackbuf[q] = 0;
2296 floatsel[q] = 0;
2297 }
2298 }
2299 else
2300 {
2301 //Delete selection
2302 for(auto x = 0; x < 16; ++x)
2303 for(auto y = 0; y < 16; ++y)
2304 {
2305 if(floating_sel)
2306 {
2307 floatsel[x+(y<<4)] = 0;
2308 }
2309 else if(is_in_selection(x,y))
2310 {
2311 unpackbuf[(y<<4)+x] = 0;
2312 }
2313 }
2314 }
2315 pack_tile(newtilebuf, unpackbuf, tile);
2316 redraw=true;
2317 }
2318 break;
2319
2320 case KEY_A:
2321 clear_selection_grid();
2322 invert_selection_grid();
2323 redraw=true;
2324 break;
2325
2326 case KEY_D:
2327 clear_selection_grid();
2328 redraw=true;
2329 break;
2330
2331 case KEY_I:
2332 invert_selection_grid();
2333 redraw=true;
2334 break;
2335
2336 case KEY_H:
2337 flip^=1;
2338 normalize(tile,tile,0,flip);
2339 flip=0;
2340 redraw=true;
2341 break;
2342
2343 case KEY_V:
2344 flip^=2;
2345 normalize(tile,tile,0,flip);
2346 flip=0;
2347 redraw=true;
2348 break;
2349
2350 case KEY_F12:
2351 onSnapshot();
2352 break;
2353
2354 case KEY_R:
2355 {
2356 //if(CHECK_CTRL_CMD))
2357 // {
2358 //do_recolor(tile); redraw=true; saved=false;
2359 // }
2360 //else
2361 // {
2362 go_tiles();
2363 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2364 redraw=true;
2365 saved=false;
2366 break;
2367 }
2368
2369 case KEY_EQUALS:
2370 case KEY_PLUS_PAD:
2371 {
2372 if(CHECK_CTRL_CMD ||
2373 key[KEY_ALT] || key[KEY_ALTGR])
2374 {
2375 for(int32_t i=0; i<undocount; i++)
2376 undotile[i]=newtilebuf[tile].data[i];
2377 for(auto x = 0; x < 16; ++x)
2378 for(auto y = 0; y < 16; ++y)
2379 undoselgrid[x][y] = selection_grid[x+1][y+1];
2380 for(auto q = 0; q < 256; ++q)
2381 undofloatsel[q] = floatsel[q];
2382 undo_is_floatsel = floating_sel;
2383
2384 if(key[KEY_ALT] || key[KEY_ALTGR])
2385 shift_tile_colors(tile, 16, false);
2386 else
2387 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2388 }
2389 else
2390 cs = (cs<13) ? cs+1:0;
2391
2392 redraw=true;
2393 break;
2394 }
2395
2396 case KEY_MINUS:
2397 case KEY_MINUS_PAD:
2398 {
2399 if(CHECK_CTRL_CMD ||
2400 key[KEY_ALT] || key[KEY_ALTGR])
2401 {
2402 for(int32_t i=0; i<undocount; i++)
2403 undotile[i]=newtilebuf[tile].data[i];
2404 for(auto x = 0; x < 16; ++x)
2405 for(auto y = 0; y < 16; ++y)
2406 undoselgrid[x][y] = selection_grid[x+1][y+1];
2407 for(auto q = 0; q < 256; ++q)
2408 undofloatsel[q] = floatsel[q];
2409 undo_is_floatsel = floating_sel;
2410
2411 if(key[KEY_ALT] || key[KEY_ALTGR])
2412 shift_tile_colors(tile, -16, false);
2413 else
2414 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2415 }
2416 else
2417 cs = (cs>0) ? cs-1:13;
2418
2419 redraw=true;
2420 break;
2421 }
2422
2423 case KEY_SPACE:
2424 gridmode=(gridmode+1)%gm_max;
2425 redraw=true;
2426 break;
2427
2428 case KEY_Z:
2429 if(!ctrl)
2430 break;
2431 //Ctrl+Z == undo
2432 [[fallthrough]];
2433 case KEY_U:
2434 for(int32_t i=0; i<undocount; i++)
2435 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2436
2437 for(auto x = 0; x < 16; ++x)
2438 for(auto y = 0; y < 16; ++y)
2439 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2440
2441 for(auto q = 0; q < 256; ++q)
2442 zc_swap(undofloatsel[q], floatsel[q]);
2443 zc_swap(undo_is_floatsel, floating_sel);
2444
2445 redraw=true;
2446 break;
2447
2448 case KEY_S:
2449 if(CHECK_CTRL_CMD)
2450 {
2451 for(int32_t i=0; i<undocount; i++)
2452 {
2453 undotile[i]=newtilebuf[tile].data[i];
2454 }
2455 for(auto x = 0; x < 16; ++x)
2456 for(auto y = 0; y < 16; ++y)
2457 undoselgrid[x][y] = selection_grid[x+1][y+1];
2458 for(auto q = 0; q < 256; ++q)
2459 undofloatsel[q] = floatsel[q];
2460 undo_is_floatsel = floating_sel;
2461
2462 unpack_tile(newtilebuf, tile, 0, false);
2463
2464 if(has_selection())
2465 {
2466 for(int32_t i=0; i<256; i++)
2467 {
2468 if(!is_in_selection(i%16,i/16))
2469 continue;
2470 if(unpackbuf[i]==c1)
2471 {
2472 unpackbuf[i]=c2;
2473 }
2474 else if(unpackbuf[i]==c2)
2475 {
2476 unpackbuf[i]=c1;
2477 }
2478 if(floating_sel)
2479 {
2480 if(floatsel[i]==c1)
2481 {
2482 floatsel[i]=c2;
2483 }
2484 else if(floatsel[i]==c2)
2485 {
2486 floatsel[i]=c1;
2487 }
2488 }
2489 }
2490 }
2491 else
2492 {
2493 for(int32_t i=0; i<256; i++)
2494 {
2495 if(unpackbuf[i]==c1)
2496 {
2497 unpackbuf[i]=c2;
2498 }
2499 else if(unpackbuf[i]==c2)
2500 {
2501 unpackbuf[i]=c1;
2502 }
2503 }
2504 }
2505
2506 pack_tile(newtilebuf, unpackbuf,tile);
2507 }
2508
2509 zc_swap(c1,c2);
2510 redraw=true;
2511 break;
2512
2513 case KEY_UP:
2514 if(CHECK_CTRL_CMD)
2515 {
2516 unfloat_selection();
2517 tile=zc_max(0,tile-TILES_PER_ROW);
2518 undocount = tilesize(newtilebuf[tile].format);
2519
2520 for(int32_t i=0; i<undocount; i++)
2521 {
2522 undotile[i]=newtilebuf[tile].data[i];
2523 oldtile[i]=undotile[i];
2524 }
2525
2526 redraw=true;
2527 }
2528 else
2529 {
2530 for(int32_t i=0; i<undocount; i++)
2531 {
2532 undotile[i]=newtilebuf[tile].data[i];
2533 }
2534 for(auto x = 0; x < 16; ++x)
2535 for(auto y = 0; y < 16; ++y)
2536 undoselgrid[x][y] = selection_grid[x+1][y+1];
2537 for(auto q = 0; q < 256; ++q)
2538 undofloatsel[q] = floatsel[q];
2539 undo_is_floatsel = floating_sel;
2540 if(has_selection())
2541 {
2542 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2543 wrap_sel_tile(-1, 0);
2544 shift_selection_grid(0, -1);
2545 }
2546 else wrap_tile(tile, -1, 0, false);
2547 redraw=true;
2548 }
2549 break;
2550
2551 case KEY_DOWN:
2552 if(CHECK_CTRL_CMD)
2553 {
2554 unfloat_selection();
2555 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2556 undocount = tilesize(newtilebuf[tile].format);
2557
2558 for(int32_t i=0; i<undocount; i++)
2559 {
2560 undotile[i]=newtilebuf[tile].data[i];
2561 oldtile[i]=undotile[i];
2562 }
2563
2564 redraw=true;
2565 }
2566 else
2567 {
2568 for(int32_t i=0; i<undocount; i++)
2569 {
2570 undotile[i]=newtilebuf[tile].data[i];
2571 }
2572 for(auto x = 0; x < 16; ++x)
2573 for(auto y = 0; y < 16; ++y)
2574 undoselgrid[x][y] = selection_grid[x+1][y+1];
2575 for(auto q = 0; q < 256; ++q)
2576 undofloatsel[q] = floatsel[q];
2577 undo_is_floatsel = floating_sel;
2578 if(has_selection())
2579 {
2580 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2581 wrap_sel_tile(1, 0);
2582 shift_selection_grid(0, 1);
2583 }
2584 else wrap_tile(tile, 1, 0, false);
2585 redraw=true;
2586 }
2587 break;
2588
2589 case KEY_LEFT:
2590 if(CHECK_CTRL_CMD)
2591 {
2592 unfloat_selection();
2593 tile=zc_max(0,tile-1);
2594 undocount = tilesize(newtilebuf[tile].format);
2595
2596 for(int32_t i=0; i<undocount; i++)
2597 {
2598 undotile[i]=newtilebuf[tile].data[i];
2599 oldtile[i]=undotile[i];
2600 }
2601
2602 redraw=true;
2603 }
2604 else
2605 {
2606 for(int32_t i=0; i<undocount; i++)
2607 {
2608 undotile[i]=newtilebuf[tile].data[i];
2609 }
2610 for(auto x = 0; x < 16; ++x)
2611 for(auto y = 0; y < 16; ++y)
2612 undoselgrid[x][y] = selection_grid[x+1][y+1];
2613 for(auto q = 0; q < 256; ++q)
2614 undofloatsel[q] = floatsel[q];
2615 undo_is_floatsel = floating_sel;
2616 if(has_selection())
2617 {
2618 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2619 wrap_sel_tile(0, -1);
2620 shift_selection_grid(-1, 0);
2621 }
2622 else wrap_tile(tile, 0, -1, false);
2623 redraw=true;
2624 }
2625 break;
2626
2627 case KEY_RIGHT:
2628 if(CHECK_CTRL_CMD)
2629 {
2630 unfloat_selection();
2631 tile=zc_min(tile+1, NEWMAXTILES-1);
2632 undocount = tilesize(newtilebuf[tile].format);
2633
2634 for(int32_t i=0; i<undocount; i++)
2635 {
2636 undotile[i]=newtilebuf[tile].data[i];
2637 oldtile[i]=undotile[i];
2638 }
2639
2640 redraw=true;
2641 }
2642 else
2643 {
2644 for(int32_t i=0; i<undocount; i++)
2645 {
2646 undotile[i]=newtilebuf[tile].data[i];
2647 }
2648 for(auto x = 0; x < 16; ++x)
2649 for(auto y = 0; y < 16; ++y)
2650 undoselgrid[x][y] = selection_grid[x+1][y+1];
2651 for(auto q = 0; q < 256; ++q)
2652 undofloatsel[q] = floatsel[q];
2653 undo_is_floatsel = floating_sel;
2654 if(has_selection())
2655 {
2656 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2657 wrap_sel_tile(0, 1);
2658 shift_selection_grid(1, 0);
2659 }
2660 else wrap_tile(tile, 0, 1, false);
2661 redraw=true;
2662 }
2663 break;
2664 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2665 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2666 case KEY_8: case KEY_9:
2667 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2668 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2669 case KEY_8_PAD: case KEY_9_PAD:
2670 {
2671 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2672 if(unsigned(t) < t_max)
2673 {
2674 if(old_tool != -1)
2675 old_tool = t;
2676 else tool = t;
2677 }
2678 break;
2679 }
2680 case KEY_TAB:
2681 {
2682 if(key_shifts & KB_CTRL_FLAG)
2683 {
2684 xmode = (xmode+1)%XMODE_MAX;
2685 if(!xmode)
2686 bgmode = (bgmode+1)%BGMODE_MAX;
2687 }
2688 else if(key_shifts & KB_SHIFT_FLAG)
2689 hide_grid = !hide_grid;
2690 else show_quartgrid = !show_quartgrid;
2691 redraw = true;
2692 break;
2693 }
2694 }
2695 clear_keybuf();
2696 }
2697
2698 if(!gui_mouse_b())
2699 {
2700 if(is_selecting())
2701 {
2702 unfloat_selection();
2703 int32_t x1=zc_min(selecting_x1,selecting_x2);
2704 int32_t x2=zc_max(selecting_x1,selecting_x2);
2705 int32_t y1=zc_min(selecting_y1,selecting_y2);
2706 int32_t y2=zc_max(selecting_y1,selecting_y2);
2707
2708 if(select_mode==0)
2709 {
2710 clear_selection_grid();
2711 }
2712
2713 for(int32_t x=x1; x<=x2; ++x)
2714 {
2715 for(int32_t y=y1; y<=y2; ++y)
2716 {
2717 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2718 }
2719 }
2720
2721 if(select_mode==3)
2722 {
2723 for(int32_t y=0; y<16; ++y)
2724 {
2725 for(int32_t x=0; x<x1; ++x)
2726 {
2727 selection_grid[x+1][y+1]=0;
2728 }
2729
2730 for(int32_t x=x2+1; x<16; ++x)
2731 {
2732 selection_grid[x+1][y+1]=0;
2733 }
2734 }
2735
2736 for(int32_t x=x1; x<=x2; ++x)
2737 {
2738 for(int32_t y=0; y<y1; ++y)
2739 {
2740 selection_grid[x+1][y+1]=0;
2741 }
2742
2743 for(int32_t y=y2+1; y<16; ++y)
2744 {
2745 selection_grid[x+1][y+1]=0;
2746 }
2747 }
2748 }
2749 }
2750
2751 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2752 did_wand_select=false;
2753 }
2754
2755 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2756 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2757 bool ctrl=CHECK_CTRL_CMD;
2758 static int32_t last_tool_val = 0;
2759
2760 if(tool==t_select||tool==t_wand)
2761 {
2762 if(!drawing)
2763 {
2764 int32_t type=0;
2765
2766 if(has_selection())
2767 {
2768 if(shift)
2769 {
2770 type+=1;
2771 }
2772
2773 if(alt)
2774 {
2775 type+=2;
2776 }
2777 }
2778
2779 if(type!=select_mode)
2780 {
2781 select_mode=type;
2782
2783 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2784 set_tool_sprite(tool,type);
2785 }
2786 }
2787 }
2788 else if(alt||ctrl)
2789 {
2790 if(old_tool==-1)
2791 {
2792 old_tool = tool;
2793 tool_cur = -1;
2794 }
2795 if(alt&&ctrl)
2796 tool = t_recolor;
2797 else if(alt)
2798 tool = t_eyedropper;
2799 else tool = t_fill;
2800 }
2801 else if(old_tool!=-1)
2802 {
2803 tool = old_tool;
2804 old_tool = -1;
2805 tool_cur = -1;
2806 redraw = true;
2807 }
2808 if(last_tool_val != tool)
2809 {
2810 redraw = true;
2811 tool_cur = -1;
2812 update_tool_cursor();
2813 last_tool_val = tool;
2814 }
2815
2816 if(!bdown)
2817 {
2818 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2819 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2820 }
2821
2822 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2823 {
2824 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2825 {
2826 if(tool==t_move || tool==t_fill)
2827 {
2828 set_tool_sprite(tool,1);
2829
2830 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2831 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2832 }
2833
2834 for(int32_t i=0; i<undocount; i++)
2835 {
2836 undotile[i]=newtilebuf[tile].data[i];
2837 }
2838 for(auto x = 0; x < 16; ++x)
2839 for(auto y = 0; y < 16; ++y)
2840 undoselgrid[x][y] = selection_grid[x+1][y+1];
2841 for(auto q = 0; q < 256; ++q)
2842 undofloatsel[q] = floatsel[q];
2843 undo_is_floatsel = floating_sel;
2844
2845 drawing=1;
2846 }
2847
2848 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2849 {
2850 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2851 {
2852 done=2;
2853 }
2854 }
2855
2856 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2857 {
2858 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2859 {
2860 done=1;
2861 }
2862 }
2863
2864 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2865 {
2866 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2867 {
2868 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2869 get_palette(tpal);
2870
2871 if(newtilebuf[tile].format==tf4Bit)
2872 {
2873 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2874 }
2875 else
2876 {
2877 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2878 }
2879
2880 redraw=true;
2881 }
2882 }
2883
2884 int sqr_clicked;
2885 if(show_quartgrid && qgrid_tool(tool))
2886 {
2887 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2888 if(sqr_clicked > -1)
2889 {
2890 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2891 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2892 refl_flags ^= (1<<sqr_clicked);
2893 }
2894 }
2895 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2896 if(sqr_clicked > -1)
2897 {
2898 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2899 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2900 xmode = sqr_clicked;
2901 }
2902 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2903 if(sqr_clicked > -1)
2904 {
2905 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2906 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2907 bgmode = sqr_clicked;
2908 }
2909
2910 if(showcolortip)
2911 {
2912 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2913 {
2914 showcolortip = 0;
2915 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2916 }
2917 }
2918 else
2919 {
2920 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2921 {
2922 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2923 {
2924 showcolortip = 1;
2925 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2926 redraw=true;
2927 }
2928 }
2929 }
2930
2931 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2932 {
2933 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2934 {
2935 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2936 redraw=true;
2937 }
2938 }
2939 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2940 {
2941 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2942 redraw=true;
2943 }
2944 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2945 {
2946 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2947 redraw=true;
2948 }
2949
2950 switch(newtilebuf[tile].format)
2951 {
2952 case tf4Bit:
2953 {
2954 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2955 if(ind > -1)
2956 {
2957 c1 = ind;
2958 redraw=true;
2959 }
2960 break;
2961 }
2962 case tf8Bit:
2963 {
2964 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2965 if(ind > -1)
2966 {
2967 c1 = ind;
2968 redraw=true;
2969 }
2970 break;
2971 }
2972 }
2973
2974
2975 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2976 if(newtool > -1 && newtool < t_max)
2977 {
2978 tool=newtool;
2979 redraw=true;
2980 }
2981
2982 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
2983 {
2984 if(do_x_button(screen, x_btn.x, x_btn.y))
2985 {
2986 done=1;
2987 }
2988 }
2989 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
2990 {
2991 if(do_question_button(screen, info_btn.x, info_btn.y))
2992 {
2993 show_edit_tile_help();
2994 }
2995 }
2996
2997 bdown=true;
2998 }
2999
3000 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3001 {
3002 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3003 {
3004 if(tool==t_move || tool==t_fill)
3005 {
3006 set_tool_sprite(tool,1);
3007
3008 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3009 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3010 }
3011
3012 for(int32_t i=0; i<undocount; i++)
3013 {
3014 undotile[i]=newtilebuf[tile].data[i];
3015 }
3016 for(auto x = 0; x < 16; ++x)
3017 for(auto y = 0; y < 16; ++y)
3018 undoselgrid[x][y] = selection_grid[x+1][y+1];
3019 for(auto q = 0; q < 256; ++q)
3020 undofloatsel[q] = floatsel[q];
3021 undo_is_floatsel = floating_sel;
3022
3023 drawing=2;
3024 }
3025
3026 switch(newtilebuf[tile].format)
3027 {
3028 case tf4Bit:
3029 {
3030 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3031 if(ind > -1)
3032 {
3033 c2 = ind;
3034 redraw=true;
3035 }
3036 break;
3037 }
3038 case tf8Bit:
3039 {
3040 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3041 if(ind > -1)
3042 {
3043 c2 = ind;
3044 redraw=true;
3045 }
3046 break;
3047 }
3048 }
3049
3050 bdown=true;
3051 }
3052
3053 if(bdown&&!gui_mouse_b()) //released the buttons
3054 {
3055 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3056 {
3057 if(tool==t_move || tool==t_fill)
3058 {
3059 set_tool_sprite(tool,0);
3060 }
3061 }
3062 }
3063
3064 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3065 {
3066 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3067 int32_t x=ind%zoomtile.w;
3068 int32_t y=ind/zoomtile.w;
3069
3070 bool reset_draw = false;
3071
3072 if(__pixel_draw(x,y,tile,flip))
3073 reset_draw = true;
3074 if(show_quartgrid)
3075 {
3076 auto tmp_sel_mode = select_mode;
3077 if(tool == t_wand && select_mode == 0)
3078 select_mode = 1;
3079 if(qgrid_tool(tool))
3080 {
3081 if(refl_flags & (1<<REFL_HFLIP))
3082 if(__pixel_draw(15-x,y,tile,flip))
3083 reset_draw = true;
3084 if(refl_flags & (1<<REFL_VFLIP))
3085 if(__pixel_draw(x,15-y,tile,flip))
3086 reset_draw = true;
3087 //Diagonal flip and 180° rotation are the same!
3088 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3089 if(__pixel_draw(15-x,15-y,tile,flip))
3090 reset_draw = true;
3091 if(refl_flags & (1<<REFL_90CW))
3092 if(__pixel_draw(15-y,x,tile,flip))
3093 reset_draw = true;
3094 if(refl_flags & (1<<REFL_90CCW))
3095 if(__pixel_draw(y,15-x,tile,flip))
3096 reset_draw = true;
3097 }
3098 select_mode = tmp_sel_mode;
3099 }
3100
3101 if(reset_draw)
3102 drawing = 0;
3103 redraw=true;
3104 }
3105
3106 if(gui_mouse_b()==0)
3107 {
3108 bdown=false;
3109 drawing=0;
3110 }
3111
3112 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3113 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3114
3115 {
3116 tile_x=temp_x;
3117 tile_y=temp_y;
3118 redraw=true;
3119 }
3120
3121 const char *toolnames[t_max]=
3122 {
3123 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3124 };
3125
3126 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3127 if(toolbtn > -1 && toolbtn < t_max)
3128 {
3129 int32_t column = toolbtn%tool_btns.w;
3130 int32_t row = toolbtn/tool_btns.w;
3131
3132 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3133 redraw=true;
3134 }
3135 /* Highlight the hovered pixel? Eh, maybe too much?
3136 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3137 if(hov_pix > -1)
3138 {
3139 int32_t column = hov_pix%zoomtile.w;
3140 int32_t row = hov_pix/zoomtile.w;
3141
3142 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3143 redraw=true;
3144 }*/
3145
3146 if(redraw)
3147 {
3148 custom_vsync();
3149 draw_edit_scr(tile,flip,cs,oldtile, false);
3150 }
3151 else
3152 {
3153 bool hs=has_selection();
3154
3155 if(hs)
3156 {
3157 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3158 }
3159
3160 custom_vsync();
3161
3162 if(hs)
3163 {
3164 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3165 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3166 }
3167
3168 update_tool_cursor();
3169 SCRFIX();
3170 }
3171
3172 }
3173 while(!done);
3174
3175 unfloat_selection();
3176 clear_selection_grid();
3177
3178 while(gui_mouse_b())
3179 {
3180 /* do nothing */
3181 rest(1);
3182 }
3183
3184 if(done==1)
3185 {
3186 for(int32_t i=0; i<undocount; i++)
3187 {
3188 newtilebuf[tile].data[i]=oldtile[i];
3189 }
3190 }
3191 else
3192 {
3193 byte *buf = new byte[undocount];
3194
3195 // put back old tile
3196 for(int32_t i=0; i<undocount; i++)
3197 {
3198 buf[i] = newtilebuf[tile].data[i];
3199 newtilebuf[tile].data[i] = oldtile[i];
3200 }
3201
3202 // go
3203 go_tiles();
3204
3205 // replace old tile with new one again
3206 for(int32_t i=0; i<undocount; i++)
3207 {
3208 newtilebuf[tile].data[i] = buf[i];
3209 }
3210
3211 // usetiles=true;
3212 saved=false;
3213
3214 if(buf!=NULL)
3215 {
3216 delete[] buf;
3217 }
3218 }
3219
3220 MouseSprite::set(ZQM_NORMAL);
3221 register_blank_tiles();
3222 register_used_tiles();
3223 clear_tooltip();
3224 comeback();
3225 destroy_bitmap(selection_pattern);
3226 destroy_bitmap(selecting_pattern);
3227 destroy_bitmap(intersection_pattern);
3228 font = oldfont;
3229 popup_zqdialog_end();
3230 }
3231
3232 /* Grab Tile Code */
3233
3234 enum recolorState { rcNone, rc4Bit, rc8Bit };
3235
3236 BITMAP* original_imagebuf_bitmap=NULL;
3237 void *imagebuf=NULL;
3238 int32_t imagebuf_bitmap_scale=0;
3239 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3240 int32_t imagesize=0;
3241 int32_t tilecount=0;
3242 int32_t imagetype=0;
3243 int32_t imagex,imagey,selx,sely;
3244 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3245 bool nesmode=false;
3246 int32_t grabmask=0;
3247 recolorState recolor=rcNone;
3248 PALETTE imagepal;
3249
3250 /* bestfit_color:
3251 * Searches a palette for the color closest to the requested R, G, B value.
3252 */
3253 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3254 {
3255 int32_t bestMatch = 0; // Color with the lowest total difference so far
3256 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3257 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3258
3259 for(int32_t i = 0; i < CSET_SIZE; i++)
3260 {
3261 byte *rgbByte;
3262
3263 // This seems to be right...
3264 if(cs==2 || cs==3 || cs==4)
3265 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3266 else if(cs==9)
3267 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3268 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3269 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3270 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3271 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3272 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3273 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3274 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3275 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3276 else
3277 rgbByte = colordata + (CSET(cs)+i)*3;
3278
3279 int32_t dr=r-*rgbByte;
3280 int32_t dg=g-*(rgbByte+1);
3281 int32_t db=b-*(rgbByte+2);
3282
3283 // Track both the total color difference and the single greatest
3284 // difference of R, G, B. The idea is that it's better to have
3285 // two or three small differences than one big one.
3286 // The differences are multiplied by different numbers to account
3287 // for the differences in perceived brightness of the three colors.
3288 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3289 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3290
3291 // Perfect match? Just stop here.
3292 if(totalDiff==0)
3293 return i;
3294
3295 if(totalDiff < bestTotalDiff || // Best match so far?
3296 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3297 {
3298 bestMatch=i;
3299 bestTotalDiff=totalDiff;
3300 bestHighDiff=highDiff;
3301 }
3302 }
3303
3304 return bestMatch;
3305 }
3306
3307 // Same as the above, but draws from all colors in CSets 0-11.
3308 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3309 {
3310 int32_t bestMatch = 0;
3311 float bestTotalDiff = 100000;
3312 float bestHighDiff = 100000;
3313
3314 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3315 {
3316 byte *rgbByte;
3317
3318 int32_t cs=i>>4;
3319 if(cs==2 || cs==3 || cs==4)
3320 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3321 else if(cs==9)
3322 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3323 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3324 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3325 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3326 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3327 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3328 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3329 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3330 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3331 else
3332 rgbByte = colordata + i * 3;
3333
3334 int32_t dr=r-*rgbByte;
3335 int32_t dg=g-*(rgbByte+1);
3336 int32_t db=b-*(rgbByte+2);
3337
3338 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3339 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3340
3341 if(totalDiff==0) // Perfect match?
3342 return i;
3343
3344 if(totalDiff < bestTotalDiff || // Best match so far?
3345 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3346 {
3347 bestMatch=i;
3348 bestTotalDiff=totalDiff;
3349 bestHighDiff=highDiff;
3350 }
3351 }
3352
3353 return bestMatch;
3354 }
3355
3356 byte cset_reduce_table[PAL_SIZE];
3357
3358 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3359 {
3360 for(int32_t i=0; i<PAL_SIZE; i++)
3361 {
3362 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3363 }
3364 }
3365
3366 void calc_cset_reduce_table_8bit(PALETTE pal)
3367 {
3368 for(int32_t i=0; i<PAL_SIZE; i++)
3369 {
3370 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3371 }
3372 }
3373
3374 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3375 {
3376 //storage space for the grabbed image
3377 byte buf[64];
3378 memset(buf,0,64);
3379 byte *oldsrc=src;
3380
3381 //for 8 lines in the source image...
3382 for(int32_t line=0; line<(nesmode?4:8); line++)
3383 {
3384 //bx is the pixel at the start of a line in the storage buffer
3385 int32_t bx=line<<(nesmode?4:3);
3386 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3387 byte b=src[(bp&1)?line:line<<1];
3388
3389 //fill the storage buffer with data from the source image
3390 for(int32_t i=7; i>=0; --i)
3391 {
3392 buf[bx+i] = (b&1)+(cs<<4);
3393 b>>=1;
3394 }
3395 }
3396
3397 ++src;
3398
3399 for(int32_t p=1; p<bp; p++)
3400 {
3401 for(int32_t line=0; line<(nesmode?4:8); line++)
3402 {
3403 int32_t bx=line<<(nesmode?4:3);
3404 byte b=src[(bp&1)?line:line<<1];
3405
3406 for(int32_t i=7; i>=0; --i)
3407 {
3408 if(nesmode)
3409 {
3410 buf[bx+8+i] = (b&1)+(cs<<4);
3411 }
3412 else
3413 {
3414 buf[bx+i] |= (b&1)<<p;
3415 }
3416
3417 b>>=1;
3418 }
3419 }
3420
3421 if(p&1)
3422 {
3423 src+=15;
3424 }
3425 else
3426 {
3427 ++src;
3428 }
3429 }
3430
3431
3432 if(nesmode)
3433 {
3434 src=oldsrc;
3435
3436 for(int32_t counter=0; counter<2; ++counter, ++src)
3437 {
3438 //for 8 lines in the source image...
3439 for(int32_t line=0; line<4; line++)
3440 {
3441 //bx is the pixel at the start of a line in the storage buffer
3442 int32_t bx=line<<4;
3443 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3444 byte b=src[(line+4)<<1];
3445
3446 //fill the storage buffer with data from the source image
3447 for(int32_t i=7; i>=0; --i)
3448 {
3449 // buf[bx+i] = (b&1)+(cs<<4);
3450 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3451 b>>=1;
3452 }
3453 }
3454 }
3455 }
3456
3457 int32_t c=0;
3458
3459 switch(romtilemode)
3460 {
3461 case 0:
3462 case 1:
3463 case 2:
3464 for(int32_t j=0; j<8; j++)
3465 {
3466 for(int32_t i=0; i<8; i++)
3467 {
3468 putpixel(dest,x+i,y+j,buf[c++]);
3469 }
3470 }
3471
3472 break;
3473
3474 case 3:
3475 for(int32_t j=0; j<4; j++)
3476 {
3477 for(int32_t i=0; i<16; i++)
3478 {
3479 putpixel(dest,x+i,y+j,buf[c++]);
3480 }
3481 }
3482
3483 break;
3484 }
3485 }
3486
3487 const char *file_type[ftMAX]=
3488 {
3489 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3490 };
3491
3492 void draw_grab_window()
3493 {
3494 int w = 640;
3495 int h = 480;
3496 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3497 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3498 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3499 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3500
3501 FONT *oldfont = font;
3502 font = get_zc_font(font_lfont);
3503 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3504 font=oldfont;
3505 }
3506
3507 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3508 {
3509 width=width;
3510 height=height;
3511 white=white; // happy birthday compiler
3512
3513 int32_t yofs=0;
3514 //clear_to_color(screen2,bg);
3515 rectfill(screen2, 0, 0, 319, 159, black);
3516 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3517 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3518 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3519 yofs=3;
3520
3521 // text_mode(-1);
3522 int32_t tileromcolumns=20;
3523
3524 switch(imagetype)
3525 {
3526 case ftBMP:
3527 if(recolor==rcNone)
3528 {
3529 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3530 }
3531 else
3532 {
3533 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3534 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3535
3536 for(int32_t y=0; y<maxy; y++)
3537 {
3538 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3539 {
3540 break;
3541 }
3542
3543 for(int32_t x=0; x<maxx; x++)
3544 {
3545 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3546 {
3547 break;
3548 }
3549
3550 if(recolor==rc8Bit)
3551 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3552 else
3553 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3554 }
3555 }
3556 }
3557
3558 break;
3559
3560 case ftZGP:
3561 case ftQST:
3562 case ftZQT:
3563 case ftQSU:
3564 case ftTIL:
3565 {
3566 tiledata *hold = newtilebuf;
3567 newtilebuf = grabtilebuf;
3568 //fixme
3569 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3570 int32_t t=imagey*TILES_PER_ROW;
3571
3572 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3573 {
3574 if(t <= tilecount)
3575 {
3576 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3577 }
3578
3579 ++t;
3580 }
3581
3582 newtilebuf = hold;
3583 //fixme
3584 }
3585 break;
3586
3587 case ftBIN:
3588 {
3589 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3590 byte *buf = (byte*)imagebuf;
3591
3592 switch(romtilemode)
3593 {
3594 case 0:
3595 for(int32_t y=0; y<160; y+=8)
3596 {
3597 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3598 {
3599 puttileROM(screen2,x,y,buf+ofs,cs);
3600 ofs+=8*bp;
3601 }
3602 }
3603
3604 for(int32_t y=0; y<160; y+=8)
3605 {
3606 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3607 {
3608 puttileROM(screen2,x+128,y,buf+ofs,cs);
3609 ofs+=8*bp;
3610 }
3611 }
3612
3613 break;
3614
3615 case 1:
3616 for(int32_t y=0; y<160; y+=16)
3617 {
3618 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3619 {
3620 puttileROM(screen2,x,y,buf+ofs,cs);
3621 ofs+=8*bp;
3622 puttileROM(screen2,x,y+8,buf+ofs,cs);
3623 ofs+=8*bp;
3624 }
3625 }
3626
3627 for(int32_t y=0; y<160; y+=16)
3628 {
3629 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3630 {
3631 puttileROM(screen2,x+128,y,buf+ofs,cs);
3632 ofs+=8*bp;
3633 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3634 ofs+=8*bp;
3635 }
3636 }
3637
3638 break;
3639
3640 case 2:
3641 for(int32_t y=0; y<160; y+=16)
3642 {
3643 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3644 {
3645 puttileROM(screen2,x,y,buf+ofs,cs);
3646 ofs+=8*bp;
3647 puttileROM(screen2,x+8,y,buf+ofs,cs);
3648 ofs+=8*bp;
3649 puttileROM(screen2,x,y+8,buf+ofs,cs);
3650 ofs+=8*bp;
3651 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3652 ofs+=8*bp;
3653 }
3654 }
3655
3656 for(int32_t y=0; y<160; y+=16)
3657 {
3658 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3659 {
3660 puttileROM(screen2,x+128,y,buf+ofs,cs);
3661 ofs+=8*bp;
3662 puttileROM(screen2,x+136,y,buf+ofs,cs);
3663 ofs+=8*bp;
3664 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3665 ofs+=8*bp;
3666 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3667 ofs+=8*bp;
3668 }
3669 }
3670
3671 break;
3672
3673 case 3:
3674 for(int32_t y=0; y<160; y+=16)
3675 {
3676 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3677 {
3678 puttileROM(screen2,x,y,buf+ofs,cs);
3679 ofs+=8*bp;
3680 puttileROM(screen2,x,y+4,buf+ofs,cs);
3681 ofs+=8*bp;
3682 puttileROM(screen2,x,y+8,buf+ofs,cs);
3683 ofs+=8*bp;
3684 puttileROM(screen2,x,y+12,buf+ofs,cs);
3685 ofs+=8*bp;
3686 }
3687 }
3688
3689 for(int32_t y=0; y<160; y+=16)
3690 {
3691 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3692 {
3693 puttileROM(screen2,x+128,y,buf+ofs,cs);
3694 ofs+=8*bp;
3695 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3696 ofs+=8*bp;
3697 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3698 ofs+=8*bp;
3699 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3700 ofs+=8*bp;
3701 }
3702 }
3703
3704 break;
3705 }
3706 }
3707 break;
3708 }
3709
3710 tiledata hold;
3711 bool holdblank = blank_tile_table[0];
3712
3713 if(is_valid_format(newtilebuf[0].format))
3714 {
3715 hold.format = newtilebuf[0].format;
3716 hold.data = (byte *)malloc(tilesize(hold.format));
3717 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3718 }
3719 else
3720 {
3721 hold.format=tfInvalid;
3722 hold.data=NULL;
3723 }
3724
3725 newtilebuf[0].format=newformat[0];
3726 blank_tile_table[0] = false;
3727
3728 if(newtilebuf[0].data!=NULL)
3729 {
3730 free(newtilebuf[0].data);
3731 }
3732
3733 if(is_valid_format(newtilebuf[0].format))
3734 {
3735 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3736
3737 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3738 {
3739 newtilebuf[0].data[i]=newtile[i];
3740 }
3741 }
3742 else
3743 {
3744 newtilebuf[0].data=NULL;
3745 }
3746
3747 puttile16(screen2,0,208,168+yofs,cs,0);
3748 overtile16(screen2,0,232,168+yofs,cs,0);
3749 newtilebuf[0].format=hold.format;
3750 blank_tile_table[0] = holdblank;
3751
3752 if(newtilebuf[0].data!=NULL)
3753 {
3754 free(newtilebuf[0].data);
3755 }
3756
3757 if(is_valid_format(newtilebuf[0].format))
3758 {
3759 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3760
3761 for(int32_t i=0; i<256; i++)
3762 {
3763 newtilebuf[0].data[i]=hold.data[i];
3764 }
3765 }
3766 else
3767 {
3768 newtilebuf[0].data=NULL;
3769 }
3770
3771 if(hold.data!=NULL)
3772 {
3773 free(hold.data);
3774 }
3775
3776 puttile16(screen2,tile,208,192+yofs,cs,0);
3777 overtile16(screen2,tile,232,192+yofs,cs,0);
3778
3779 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3780 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3781 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3782 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3783
3784 // rect(screen2,183,167,200,184,dvc(7*2));
3785 // rect(screen2,207,167,224,184,dvc(7*2));
3786 // rect(screen2,231,167,248,184,dvc(7*2));
3787 // rect(screen2,207,191,224,208,dvc(7*2));
3788 // rect(screen2,231,191,248,208,dvc(7*2));
3789
3790 /*
3791 rect(screen2,183,167,200,184,vc(14));
3792 rect(screen2,207,167,224,184,vc(14));
3793 rect(screen2,231,167,248,184,vc(14));
3794 rect(screen2,207,191,224,208,vc(14));
3795 rect(screen2,231,191,248,208,vc(14));
3796 */
3797 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3798 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3799 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3800 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3801 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3802 int32_t screen_xofs=6;
3803 int32_t screen_yofs=25;
3804 int winh = 511;
3805 int32_t mul = 2;
3806
3807 yofs=16;
3808
3809 custom_vsync();
3810
3811 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3812
3813 // Suspend the current font while draw_text_button does its work
3814 FONT* oldfont = font;
3815
3816 font = get_zc_font(font_lfont_l);
3817
3818 int txt_x = 8*mul;
3819 int rbtn_x = 255*mul;
3820 int max_fpath_wid = rbtn_x-2-txt_x;
3821 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3822 // Interface
3823 switch(imagetype)
3824 {
3825 case 0:
3826 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3827 break;
3828
3829 case ftBMP:
3830 {
3831 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3832 int text_x = txt_x;
3833 int text_y = (216 + yofs) * mul;
3834 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3835 // int text_w = text_length(font, text.c_str());
3836 // int text_h = text_height(font);
3837 // static int grab_scale_tooltip_id = ttip_register_id();
3838 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3839 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3840
3841 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3842 break;
3843 }
3844
3845 case ftZGP:
3846 case ftQST:
3847 case ftZQT:
3848 case ftQSU:
3849 case ftTIL:
3850 case ftBIN:
3851 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3852 break;
3853 }
3854
3855 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3856 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3857
3858 if(bp==8)
3859 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3860 else
3861 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3862 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3863
3864 if(imagetype==ftBIN)
3865 {
3866 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3867 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3868 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3869 }
3870
3871 int fpath_y = (224+yofs)*mul;
3872 if(text_length(font,imagepath) <= max_fpath_wid)
3873 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3874 else
3875 {
3876 char buf[2052] = {0};
3877 strncpy(buf,imagepath,2048);
3878 int len = strlen(buf);
3879 char *ptr = buf;
3880 char *endptr = buf+len;
3881 char *it = endptr;
3882 int tmpy = fpath_y;
3883 int tmph = text_height(font)+1;
3884 while(true)
3885 {
3886 if(tmpy+tmph > (winh-2))
3887 break; //Out of space!
3888 char c = *it;
3889 bool end = !c;
3890 *it = 0;
3891 int newlen = text_length(font,ptr);
3892 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3893 {
3894 if(end) //No stored character, string ended
3895 {
3896 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3897 break;
3898 }
3899 char t[5];
3900 t[0] = c;
3901 for(int q = 1; q < 5; ++q)
3902 t[q] = it[q];
3903 strcpy(it,"...");
3904 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3905 for(int q = 0; q < 5; ++q)
3906 it[q] = t[q];
3907 tmpy += tmph;
3908 ptr = it;
3909 it = endptr;
3910 }
3911 else
3912 {
3913 *it = c;
3914 --it;
3915 }
3916 }
3917 }
3918 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3919 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3920 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3921 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3922
3923 //int32_t rectw = 16*mul;
3924 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3925 SCRFIX();
3926 font = oldfont;
3927 }
3928
3929 RGB_MAP rgb_table;
3930 COLOR_MAP imagepal_table;
3931
3932
3933 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3934 {
3935 //these are here to bypass compiler warnings about unused arguments
3936 x=x;
3937
3938 rgb->r = pal[y].r;
3939 rgb->g = pal[y].g;
3940 rgb->b = pal[y].b;
3941 }
3942
3943
3944 void load_imagebuf()
3945 {
3946 PACKFILE *f;
3947 //cache QRS
3948 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3949 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3950 // {
3951 // cached_rules[q] = quest_rules[q];
3952 // }
3953 bool compressed=false;
3954 bool encrypted=false;
3955 tiledata *hold=newtilebuf;
3956 zquestheader tempheader;
3957 memset(&tempheader, 0, sizeof(zquestheader));
3958
3959 if(imagebuf)
3960 {
3961 switch(imagetype)
3962 {
3963 case ftBMP:
3964 if (original_imagebuf_bitmap != imagebuf)
3965 destroy_bitmap((BITMAP*)imagebuf);
3966 destroy_bitmap(original_imagebuf_bitmap);
3967 break;
3968
3969 case ftZGP:
3970 case ftQST:
3971 case ftZQT:
3972 case ftQSU:
3973 case ftTIL:
3974 clear_tiles(grabtilebuf);
3975 break;
3976
3977 case ftBIN:
3978 free(imagebuf);
3979 break;
3980 }
3981
3982 imagebuf=NULL;
3983 original_imagebuf_bitmap=NULL;
3984 }
3985
3986 selx=sely=romofs=0;
3987 bp=4;
3988 imagetype=filetype(imagepath);
3989
3990 dword section_id;
3991 dword section_version;
3992 dword section_cversion;
3993
3994 switch(imagetype)
3995 {
3996 case ftBMP:
3997 packfile_password("");
3998 memset(imagepal, 0, sizeof(PALETTE));
3999 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4000 imagesize = file_size_ex_password(imagepath,"");
4001 tilecount=0;
4002 create_rgb_table(&rgb_table, imagepal, NULL);
4003 rgb_map = &rgb_table;
4004 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4005
4006 if(!original_imagebuf_bitmap)
4007 {
4008 imagetype=0;
4009 }
4010 else
4011 {
4012 imagebuf = original_imagebuf_bitmap;
4013 imagebuf_bitmap_scale = 1;
4014 }
4015
4016 break;
4017
4018 case ftBIN:
4019 packfile_password("");
4020 imagesize = file_size_ex_password(imagepath, "");
4021 tilecount=0;
4022
4023 if(imagesize)
4024 {
4025 imagebuf = malloc(imagesize);
4026
4027 if(!readfile(imagepath,imagebuf,imagesize))
4028 {
4029 free(imagebuf);
4030 imagesize=0;
4031 imagetype=0;
4032 }
4033 }
4034
4035 break;
4036
4037 case ftTIL:
4038 packfile_password("");
4039 imagesize = file_size_ex_password(imagepath,"");
4040 f = pack_fopen_password(imagepath,F_READ,"");
4041
4042 if(!f)
4043 {
4044 goto error;
4045 }
4046
4047 if(!p_mgetl(&section_id,f))
4048 {
4049 goto error;
4050 }
4051
4052 if(section_id==ID_TILES)
4053 {
4054 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4055 {
4056 goto error;
4057 }
4058 }
4059
4060 error:
4061 pack_fclose(f);
4062 tilecount=count_tiles(grabtilebuf);
4063 break;
4064
4065 case ftZGP:
4066 packfile_password("");
4067 imagesize = file_size_ex_password(imagepath, "");
4068 f=pack_fopen_password(imagepath,F_READ,"");
4069
4070 if(!f)
4071 {
4072 goto error2;
4073 }
4074
4075 if(!p_mgetl(&section_id,f))
4076 {
4077 goto error2;
4078 }
4079
4080 if(section_id!=ID_GRAPHICSPACK)
4081 {
4082 goto error2;
4083 }
4084
4085 //section version info
4086 if(!p_igetw(&section_version,f))
4087 {
4088 goto error2;
4089 }
4090
4091 if(!p_igetw(&section_cversion,f))
4092 {
4093 goto error2;
4094 }
4095
4096 //tiles
4097 if(!p_mgetl(&section_id,f))
4098 {
4099 goto error2;
4100 }
4101
4102 if(section_id==ID_TILES)
4103 {
4104 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4105 {
4106 goto error2;
4107 }
4108 }
4109
4110 error2:
4111 pack_fclose(f);
4112 tilecount=count_tiles(grabtilebuf);
4113 break;
4114
4115 case ftQST:
4116 encrypted=true;
4117 case ftZQT:
4118 compressed=true;
4119 case ftQSU:
4120 packfile_password("");
4121 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4122 newtilebuf=grabtilebuf;
4123 byte skip_flags[4];
4124
4125 for(int32_t i=0; i<skip_max; ++i)
4126 {
4127 set_bit(skip_flags,i,1);
4128 }
4129
4130 set_bit(skip_flags,skip_tiles,0);
4131 set_bit(skip_flags,skip_header,0);
4132 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4133 if (ret)
4134 {
4135 imagetype=0;
4136 imagesize=0;
4137 clear_tiles(grabtilebuf);
4138 chop_path(imagepath);
4139 }
4140
4141 if (!ret && encrypted && compressed)
4142 {
4143 if(quest_access(imagepath, &tempheader) != 1)
4144 {
4145 imagetype=0;
4146 imagesize=0;
4147 clear_tiles(grabtilebuf);
4148 chop_path(imagepath);
4149 }
4150 }
4151
4152 //setPackfilePassword(NULL);
4153 newtilebuf=hold;
4154 tilecount=count_tiles(grabtilebuf);
4155 break;
4156 }
4157
4158 rgb_map = &zq_rgb_table;
4159 //restore cashed QRs / rules
4160
4161 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4162 // {
4163 // quest_rules[q] = cached_rules[q];
4164 // }
4165 }
4166
4167 static char bitstrbuf[32];
4168 bool leeching_from_tiles=false;
4169
4170 const char *bitlist(int32_t index, int32_t *list_size)
4171 {
4172 int32_t imported=2;
4173
4174 if(index>=0)
4175 {
4176 bound(index,0,leeching_from_tiles?2:1);
4177
4178 if(index==imported)
4179 {
4180 sprintf(bitstrbuf,"Imported");
4181 }
4182 else
4183 {
4184 sprintf(bitstrbuf,"%d",4<<index);
4185 }
4186
4187 return bitstrbuf;
4188 }
4189
4190 *list_size=leeching_from_tiles?3:2;
4191 return NULL;
4192 }
4193
4194 9 static ListData bit_list(bitlist, &font);
4195
4196 static DIALOG leech_dlg[] =
4197 {
4198 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4199 9 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4200 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4201 // 2
4202 9 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4203 9 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4204 9 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4205 // 5
4206 9 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4207 9 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4208 9 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4209 9 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4210 //9
4211 9 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4212 9 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4213
4214 9 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4215 9 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4216 9 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4217 9 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4218 9 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4219 //16
4220 9 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4221 9 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4222 9 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4223
4224 9 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4225 9 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4226 9 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4227
4228 9 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4229 9 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4230 9 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4231
4232 9 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4233 9 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4234 9 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4235
4236 9 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4237 9 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4238 9 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4239 9 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4240 9 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4241 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4242 };
4243
4244 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4245 {
4246 bool shift=true; // fix this!
4247 int32_t cst=0;
4248 int32_t currtile=start;
4249 int32_t height=0, width=0;
4250 byte *testtile = new byte[tilesize(tf32Bit)];
4251 byte imported_format=0;
4252 char updatestring[6];
4253 bool canadd;
4254 bool temp_canadd;
4255 bool duplicate;
4256 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4257 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4258 {
4259 0,0,0,0
4260 };
4261 BITMAP *status;
4262 status = create_bitmap_ex(8,240,140);
4263 clear_bitmap(status);
4264 sprintf(updatestring, "%d", LeechUpdate);
4265 leech_dlg[0].dp2=get_zc_font(font_lfont);
4266 leech_dlg[6].dp=updatestring;
4267
4268 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4269
4270 for(int32_t i=0; i<2; i++)
4271 {
4272 leech_dlg[i+7].flags=0;
4273 }
4274
4275 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4276
4277 for(int32_t i=0; i<12; i++)
4278 {
4279 leech_dlg[i+16].flags=0;
4280 }
4281
4282 for(int32_t i=0; i<4; i++)
4283 {
4284 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4285 }
4286
4287 leech_dlg[31].d1=0;
4288
4289 large_dialog(leech_dlg);
4290
4291 int32_t ret = do_zqdialog(leech_dlg,3);
4292
4293 if(ret==2)
4294 {
4295 delete[] testtile;
4296 return false;
4297 }
4298
4299 int32_t cdepth=leech_dlg[31].d1+1;
4300 int32_t newformat=0;
4301 auto lu = atoi(updatestring);
4302 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4303 if(LeechUpdate!=lu)
4304 {
4305 LeechUpdate=lu;
4306 zc_set_config("zquest","leech_update",LeechUpdate);
4307 }
4308 if(LeechUpdateTiles!=lut)
4309 {
4310 LeechUpdateTiles=lut;
4311 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4312 }
4313
4314 int32_t old_dupe[4];
4315 for(int32_t j=0; j<4; j++)
4316 {
4317 old_dupe[j] = DuplicateAction[j];
4318 for(int32_t i=0; i<3; i++)
4319 {
4320 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4321 {
4322 DuplicateAction[j]=i;
4323 }
4324 }
4325 }
4326 if(old_dupe[0] != DuplicateAction[0])
4327 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4328 if(old_dupe[1] != DuplicateAction[1])
4329 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4330 if(old_dupe[2] != DuplicateAction[2])
4331 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4332 if(old_dupe[3] != DuplicateAction[3])
4333 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4334
4335 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4336 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4337 {
4338 OnlyCheckNewTilesForDuplicates=ocntfd;
4339 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4340 }
4341
4342 leeching_from_tiles=false;
4343
4344 switch(imagetype)
4345 {
4346 case ftBIN:
4347 width=imagesize/128;
4348 height=1;
4349 break;
4350
4351 case ftZGP:
4352 case ftQST:
4353 case ftZQT:
4354 case ftQSU:
4355 case ftTIL:
4356 leeching_from_tiles=true;
4357 width=count_tiles(grabtilebuf);
4358 height=1;
4359 break;
4360
4361 case ftBMP:
4362 width=((((BITMAP*)imagebuf)->w)+15)/16;
4363 height=((((BITMAP*)imagebuf)->h)+15)/16;
4364 break;
4365 }
4366
4367 if(currtile+(width*height)>NEWMAXTILES)
4368 {
4369 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4370 {
4371 delete[] testtile;
4372 return false;
4373 }
4374 }
4375
4376 go_tiles();
4377 saved=false;
4378
4379 // usetiles=true;
4380 for(int32_t ty=0; ty<height; ty++) //for every row
4381 {
4382 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4383 {
4384 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4385 {
4386 FONT *oldfont = font;
4387 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4388 static bool created_tbar=false;
4389 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4390
4391 if(created_tbar)
4392 {
4393 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4394 }
4395 else
4396 {
4397 font = get_zc_font(font_lfont);
4398 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4399 font = oldfont;
4400 created_tbar=true;
4401 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4402 }
4403
4404 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4405 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4406 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4407 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4408 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4409 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4410 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4411 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4412 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4413 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4414 blit(status,screen,0, 0, 40, 20, 240, 140);
4415 SCRFIX();
4416 }
4417
4418 canadd=true;
4419
4420 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4421 {
4422 delete[] testtile;
4423 return true;
4424 }
4425
4426 switch(imagetype)
4427 {
4428 case ftBIN:
4429 break;
4430
4431 case ftZGP:
4432 case ftQST:
4433 case ftZQT:
4434 case ftQSU:
4435 case ftTIL:
4436 memset(testtile, 0, tilesize(tf32Bit));
4437 imported_format=grabtilebuf[tx].format;
4438
4439 switch(cdepth)
4440 {
4441 case 1: //4-bit
4442 newformat=tf4Bit;
4443
4444 switch(imported_format)
4445 {
4446 case tf4Bit:
4447 case tf8Bit:
4448 for(int32_t y=0; y<16; y++) //snag a tile
4449 {
4450 for(int32_t x=0; x<16; x+=2)
4451 {
4452 testtile[(y*8)+(x/2)]=
4453 (grabtilebuf[tx].data[y*16+x]&15)+
4454 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4455 }
4456 }
4457
4458 break;
4459 }
4460
4461 break;
4462
4463 case 2: //8-bit
4464 newformat=tf8Bit;
4465
4466 switch(imported_format)
4467 {
4468 case tf4Bit:
4469 unpack_tile(grabtilebuf, tx, 0, true);
4470 cst = cs&15;
4471 cst <<= CSET_SHFT;
4472
4473 for(int32_t i=0; i<256; i++)
4474 {
4475 if(!shift||unpackbuf[i]!=0)
4476 {
4477 unpackbuf[i]+=cst;
4478 }
4479 }
4480
4481 pack_tiledata(testtile, unpackbuf, tf8Bit);
4482 break;
4483
4484 case tf8Bit:
4485 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4486 break;
4487 }
4488
4489 break;
4490
4491 case 3: //original tile's bit depth
4492 newformat=imported_format;
4493 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4494 break;
4495 }
4496
4497 break;
4498
4499 case ftBMP:
4500 newformat=cdepth;
4501
4502 for(int32_t y=0; y<16; y++) //snag a tile
4503 {
4504 for(int32_t x=0; x<16; x+=2)
4505 {
4506 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4507 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4508 }
4509 }
4510
4511 break;
4512 }
4513
4514 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4515 {
4516 temp_canadd=true;
4517
4518 //check all tiles before this one
4519 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4520 {
4521 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4522 {
4523 if(DuplicateAction[flipping]>0)
4524 {
4525 if(keypressed())
4526 {
4527 delete[] testtile;
4528 return true;
4529 }
4530
4531 duplicate=(newformat==imported_format);
4532
4533 if(duplicate)
4534 {
4535 switch(flipping)
4536 {
4537 case 0: //normal
4538 if(dest[checktile].data!=NULL)
4539 {
4540 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4541 {
4542 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4543 {
4544 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4545 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4546 {
4547 duplicate=false;
4548 }
4549 }
4550 }
4551 }
4552
4553 break;
4554
4555 case 1: //horizontal
4556 if(dest[checktile].data!=NULL)
4557 {
4558 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4559 {
4560 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4561 {
4562 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4563 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4564 {
4565 duplicate=false;
4566 }
4567 }
4568 }
4569 }
4570
4571 break;
4572
4573 case 2: //vertical
4574 if(dest[checktile].data!=NULL)
4575 {
4576 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4577 {
4578 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4579 {
4580 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4581 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4582 {
4583 duplicate=false;
4584 }
4585 }
4586 }
4587 }
4588
4589 break;
4590
4591 case 3: //both
4592 if(dest[checktile].data!=NULL)
4593 {
4594 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4595 {
4596 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4597 {
4598 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4599 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4600 {
4601 duplicate=false;
4602 }
4603 }
4604 }
4605 }
4606
4607 break;
4608 }
4609 }
4610
4611 if(duplicate==true)
4612 {
4613 ++duplicates_found[flipping];
4614 ++total_duplicates_found;
4615
4616 if(DuplicateAction[flipping]>1)
4617 {
4618 ++total_duplicates_discarded;
4619 temp_canadd=false;
4620 }
4621 }
4622 }
4623
4624 canadd=canadd&&temp_canadd;
4625 }
4626 }
4627 }
4628
4629 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4630 dest[currtile].format=newformat;
4631
4632 if(dest[currtile].data!=NULL)
4633 {
4634 free(dest[currtile].data);
4635 }
4636
4637 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4638
4639 if(dest[currtile].data==NULL)
4640 {
4641 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4642 }
4643
4644 if(canadd==true)
4645 {
4646 /*
4647 for(int32_t y=0; y<16; y++)
4648 {
4649 for(int32_t x=0; x<8; x++)
4650 {
4651 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4652 }
4653 }
4654 */
4655 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4656 ++currtile;
4657 }
4658 }
4659 }
4660
4661 destroy_bitmap(status);
4662 delete[] testtile;
4663 return true;
4664 }
4665
4666 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4667 {
4668 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4669 byte format=defFormat;
4670 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4671
4672 switch(imagetype)
4673 {
4674 case ftZGP:
4675 case ftQST:
4676 case ftZQT:
4677 case ftQSU:
4678 case ftTIL:
4679 case ftBIN:
4680 case ftBMP:
4681 for(int32_t ty=0; ty<height; ty++)
4682 {
4683 for(int32_t tx=0; tx<width; tx++)
4684 {
4685 format=defFormat;
4686 switch(imagetype)
4687 {
4688 case ftZGP:
4689 case ftQST:
4690 case ftZQT:
4691 case ftQSU:
4692 case ftTIL:
4693 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4694 break;
4695 }
4696
4697 bool ever_did_unmasked = false;
4698
4699 for(int32_t y=0; y<16; y++)
4700 {
4701 for(int32_t x=0; x<16; x+=2)
4702 {
4703 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4704 if (masked)
4705 {
4706 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4707 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4708 }
4709 else
4710 {
4711 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4712 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4713 ever_did_unmasked = true;
4714 }
4715 if (format == tf4Bit)
4716 {
4717 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4718 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4719 }
4720 }
4721 }
4722
4723 if (ever_did_unmasked)
4724 newformat[(ty*TILES_PER_ROW)+tx] = format;
4725 }
4726 }
4727
4728 break;
4729
4730 default:
4731 for(int32_t i=0; i<200; i++)
4732 {
4733 for(int32_t j=0; j<256; j++)
4734 {
4735 dest[i][j]=0;
4736 }
4737
4738 newformat[i] = tf4Bit;
4739 }
4740
4741 break;
4742 }
4743 }
4744
4745 static void scale_imagebuf_bitmap()
4746 {
4747 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4748
4749 float scale = IMAGEBUF_SCALE;
4750 int nw = original_imagebuf_bitmap->w * scale;
4751 int nh = original_imagebuf_bitmap->h * scale;
4752 if (nw <= 0 || nh <= 0)
4753 return;
4754
4755 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4756 if (!scaled_bmp)
4757 return;
4758
4759 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4760 if (imagebuf != original_imagebuf_bitmap)
4761 destroy_bitmap((BITMAP*)imagebuf);
4762 imagebuf = scaled_bmp;
4763 }
4764
4765 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4766 void grab_tile(int32_t tile,int32_t &cs)
4767 {
4768 zq_allow_tile_draw_cache = true;
4769
4770 int window_w = 640+6+6, window_h = 480+25+6;
4771 int window_x=(zq_screen_w-window_w)/2;
4772 int window_y=(zq_screen_h-window_h)/2;
4773 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4774 int window_xofs = 0;
4775 int screen_xofs=6;
4776 int screen_yofs=25;
4777 int panel_yofs=0;
4778 int bwidth = 61*1.5;
4779 int bheight = 20*1.5;
4780 int button_x = 255*2;
4781 int grab_ok_button_y = 168*2 + 32;
4782 int leech_button_x = 117*2;
4783 int leech_button_y = 166*2 + 32;
4784 int grab_cancel_button_y = 192*2 + 32;
4785 int file_button_y = 216*2 + 32;
4786 int rec_button_x = 117*2;
4787 int rec_button_y = 192*2 + 32;
4788
4789 int screen_y1 = 24;
4790 int screen_y2 = screen_y1+320-1;
4791
4792 int crect_x = 184+190;
4793 int crect_y = 168*2 + 32;
4794 int crect_w = 8*2;
4795 int crect_h = 8*2;
4796
4797 int xrect_x = 640 + 12 - 21;
4798 int xrect_y = 5;
4799
4800 byte newtile[200][256];
4801 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4802 clear_bitmap(screen3);
4803 byte newformat[200];
4804
4805 memset(newtile, 0, 200*256);
4806 memset(newformat, 0, 200);
4807
4808 static EXT_LIST list[] =
4809 {
4810 { (char *)"All Files (*.*)", NULL },
4811 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4812 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4813 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4814 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4815 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4816 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4817 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4818 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4819 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4820 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4821 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4822 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4823 { NULL, NULL }
4824 };
4825
4826
4827 memset(cset_reduce_table, 0, 256);
4828 memset(col_diff,0,3*128);
4829 bool bdown=false;
4830 int done=0;
4831 int pal=0;
4832 int f=0;
4833 int black=vc(0),white=vc(15);
4834 int selwidth=1, selheight=1;
4835 int selx2=0, sely2=0;
4836 bool xreversed=false, yreversed=false;
4837 bool doleech=false, dofile=false, dopal=false;
4838
4839 int jwin_pal2[jcMAX];
4840 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4841
4842
4843 if(imagebuf==NULL)
4844 load_imagebuf();
4845
4846 calc_cset_reduce_table(imagepal, cs);
4847 calc_cset_reduce_table_8bit(imagepal);
4848 draw_grab_window();
4849 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4850 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4851
4852 while(gui_mouse_b())
4853 {
4854 /* do nothing */
4855 rest(1);
4856 }
4857
4858 do
4859 {
4860 HANDLE_CLOSE_ZQDLG();
4861 if(exiting_program) break;
4862 rest(4);
4863 bool redraw=false;
4864
4865 if(keypressed())
4866 {
4867 redraw=true;
4868
4869 switch(readkey()>>8)
4870 {
4871 case KEY_F:
4872 dofile=true;
4873 break;
4874
4875 case KEY_L:
4876 doleech=true;
4877 break;
4878
4879 case KEY_P:
4880 if(imagetype==ftBMP)
4881 {
4882 dopal=true;
4883 recolor=rcNone;
4884 calc_cset_reduce_table(imagepal, cs);
4885 }
4886
4887 break;
4888
4889 case KEY_ESC:
4890 done=1;
4891 break;
4892
4893 case KEY_ENTER_PAD:
4894 case KEY_ENTER:
4895 done=2;
4896 break;
4897
4898 case KEY_DOWN:
4899 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4900 else ++imagey;
4901
4902 break;
4903
4904 case KEY_UP:
4905 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4906 else --imagey;
4907
4908 break;
4909
4910 case KEY_RIGHT:
4911 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4912 else ++imagex;
4913
4914 break;
4915
4916 case KEY_LEFT:
4917 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4918 else --imagex;
4919
4920 break;
4921
4922 case KEY_PGDN:
4923 imagey+=10;
4924 break;
4925
4926 case KEY_PGUP:
4927 imagey-=10;
4928 break;
4929
4930 case KEY_HOME:
4931 imagex=imagey=0;
4932 break;
4933
4934 case KEY_EQUALS:
4935 case KEY_PLUS_PAD:
4936 cs = (cs<13) ? cs+1:0;
4937 if(recolor==rc4Bit)
4938 calc_cset_reduce_table(imagepal, cs);
4939 break;
4940
4941 case KEY_MINUS:
4942 case KEY_MINUS_PAD:
4943 cs = (cs>0) ? cs-1:13;
4944 if(recolor==rc4Bit)
4945 calc_cset_reduce_table(imagepal, cs);
4946 break;
4947
4948 case KEY_S:
4949 if(grabmode==1) grabmode=8;
4950 else if(grabmode==8) grabmode=16;
4951 else grabmode=1;
4952
4953 break;
4954
4955 case KEY_COMMA:
4956 if (imagetype == ftBMP)
4957 {
4958 imagebuf_bitmap_scale--;
4959 if (imagebuf_bitmap_scale == 0)
4960 imagebuf_bitmap_scale = -2;
4961 scale_imagebuf_bitmap();
4962 }
4963 break;
4964 case KEY_STOP:
4965 if (imagetype == ftBMP)
4966 {
4967 imagebuf_bitmap_scale++;
4968 if (imagebuf_bitmap_scale == -1)
4969 imagebuf_bitmap_scale = 1;
4970 scale_imagebuf_bitmap();
4971 }
4972 break;
4973
4974 case KEY_1:
4975 if(recolor==rc8Bit)
4976 recolor=rcNone;
4977 //imagex=(imagex*bp)>>3;
4978 bp=1;
4979 //imagex<<=3;
4980 nesmode=false;
4981 break;
4982
4983 case KEY_2:
4984 if(recolor==rc8Bit)
4985 recolor=rcNone;
4986 //imagex=(imagex*bp)>>3;
4987 bp=2;
4988 //imagex<<=2;
4989 nesmode=false;
4990 break;
4991
4992 case KEY_N:
4993 if(recolor==rc8Bit)
4994 recolor=rcNone;
4995 //imagex=(imagex*bp)>>3;
4996 bp=2;
4997 //imagex<<=2;
4998 nesmode=true;
4999 break;
5000
5001 case KEY_4:
5002 if(recolor==rc8Bit)
5003 recolor=rcNone;
5004 //imagex=(imagex*bp)>>3;
5005 bp=4;
5006 //imagex<<=1;
5007 nesmode=false;
5008 break;
5009
5010 case KEY_8:
5011 //imagex=(imagex*bp)>>3;
5012 bp=8;
5013 break;
5014
5015 case KEY_B:
5016 if(bp==2&&!nesmode)
5017 {
5018 nesmode=true;
5019 }
5020 else
5021 {
5022 nesmode=false;
5023 bp<<=1;
5024
5025 if(bp==16)
5026 {
5027 bp=1;
5028 //imagex<<=3;
5029 }
5030 else
5031 {
5032 //imagex>>=1;
5033 }
5034 }
5035
5036 break;
5037
5038 case KEY_M:
5039 romtilemode=(romtilemode+1)%4;
5040 break;
5041
5042 case KEY_Z:
5043 if(romofs>0) --romofs;
5044
5045 break;
5046
5047 case KEY_X:
5048 ++romofs;
5049 break;
5050
5051 case KEY_R:
5052 if(pal)
5053 {
5054 dopal=true;
5055 }
5056
5057 if(recolor!=rcNone)
5058 recolor=rcNone;
5059 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5060 {
5061 bp=8;
5062 recolor=rc8Bit;
5063 calc_cset_reduce_table_8bit(imagepal);
5064 }
5065 else
5066 {
5067 if(bp==8)
5068 bp=4;
5069 recolor=rc4Bit;
5070 calc_cset_reduce_table(imagepal, cs);
5071 }
5072 break;
5073
5074 default:
5075 redraw=false;
5076 }
5077
5078 clear_keybuf();
5079
5080 if(imagex<0) imagex=0;
5081
5082 if(imagey<0) imagey=0;
5083
5084 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5085 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5086 }
5087
5088 //boogie!
5089 if(gui_mouse_b()==1 && !bdown)
5090 {
5091 int x=gui_mouse_x();
5092 int y=gui_mouse_y();
5093 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5094 if(do_x_button(screen, xrect_x, xrect_y))
5095 done=1;
5096
5097 if(!bdown)
5098 {
5099 bool regrab=false;
5100 bdown=true;
5101 FONT* oldfont = font;
5102 font = get_zc_font(font_lfont_l);
5103
5104 if(y>=screen_y1 && y<=screen_y2)
5105 {
5106 do
5107 {
5108 HANDLE_CLOSE_ZQDLG();
5109 if(exiting_program) break;
5110 int x = (gui_mouse_x()-screen_xofs) / 2;
5111 int y = (gui_mouse_y()-screen_yofs) / 2;
5112
5113 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5114
5115 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5116 {
5117 selx=vbound((x/grabmode)*grabmode,0,304);
5118 sely=vbound((y/grabmode)*grabmode,0,144);
5119 selx2=selx;
5120 sely2=sely;
5121 selwidth=1;
5122 selheight=1;
5123 xreversed=false;
5124 yreversed=false;
5125 }
5126 else
5127 {
5128 if(xreversed)
5129 {
5130 zc_swap(selx, selx2);
5131 xreversed=false;
5132 }
5133
5134 if(yreversed)
5135 {
5136 zc_swap(sely, sely2);
5137 yreversed=false;
5138 }
5139
5140 selx2=vbound((x/grabmode)*grabmode,0,304);
5141 sely2=vbound((y/grabmode)*grabmode,0,144);
5142 selwidth=1+(abs(selx2-selx))/16;
5143 selheight=1+(abs(sely2-sely))/16;
5144
5145 if(selx2<selx)
5146 {
5147 zc_swap(selx, selx2);
5148 xreversed=true;
5149 }
5150
5151 if(sely2<sely)
5152 {
5153 zc_swap(sely, sely2);
5154 yreversed=true;
5155 }
5156 }
5157
5158 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5159 bool redraw = changed || !(f%8);
5160
5161 if(redraw)
5162 {
5163 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5164 if(changed)
5165 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5166 if(f&8)
5167 {
5168 static const int w = 32;
5169 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5170 }
5171 }
5172 else custom_vsync();
5173
5174 ++f;
5175 }
5176 while(gui_mouse_b());
5177 }
5178 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5179 {
5180 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5181 done=2;
5182 }
5183 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5184 {
5185 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5186 {
5187 doleech=true;
5188 }
5189 }
5190 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5191 {
5192 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5193 done=1;
5194 }
5195 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5196 {
5197 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5198 {
5199 dofile=true;
5200 }
5201 }
5202 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5203 {
5204 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5205 {
5206 if(pal)
5207 {
5208 dopal = true;
5209 }
5210
5211 if(recolor!=rcNone)
5212 recolor=rcNone;
5213 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5214 {
5215 bp=8;
5216 recolor=rc8Bit;
5217 calc_cset_reduce_table_8bit(imagepal);
5218 }
5219 else
5220 {
5221 if(bp==8)
5222 bp=4;
5223 recolor=rc4Bit;
5224 calc_cset_reduce_table(imagepal, cs);
5225 }
5226 redraw=true;
5227 }
5228 }
5229 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5230 {
5231 regrab=true;
5232 grabmask^=1;
5233 }
5234 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5235 {
5236 regrab=true;
5237 grabmask^=2;
5238 }
5239 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5240 {
5241 regrab=true;
5242 grabmask^=4;
5243 }
5244 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5245 {
5246 regrab=true;
5247 grabmask^=8;
5248 }
5249
5250 if(regrab)
5251 {
5252 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5253 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5254 redraw=true;
5255 }
5256
5257 font = oldfont;
5258 }
5259 }
5260
5261 if(gui_mouse_b()==0)
5262 bdown=false;
5263
5264 if(dofile)
5265 {
5266 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5267 {
5268 zc_set_palette(RAMpal);
5269 pal=0;
5270 white=vc(15);
5271 black=vc(0);
5272 strcpy(imagepath,temppath);
5273 load_imagebuf();
5274 imagex=imagey=0;
5275 calc_cset_reduce_table(imagepal, cs);
5276 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5277 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5278 }
5279
5280 while(key[KEY_ESC])
5281 {
5282 poll_keyboard();
5283 /* do nothing */
5284 rest(1);
5285 }
5286
5287 clear_keybuf();
5288 dofile=false;
5289 redraw=true;
5290 }
5291
5292 if(doleech)
5293 {
5294 if(leech_tiles(newtilebuf,tile,cs))
5295 {
5296 done=1;
5297 }
5298 else
5299 {
5300 while(key[KEY_ESC])
5301 {
5302 poll_keyboard();
5303 /* do nothing */
5304 rest(1);
5305 }
5306
5307 clear_keybuf();
5308 redraw=true;
5309 }
5310
5311 doleech=false;
5312 }
5313
5314 if(dopal)
5315 {
5316 pal^=1;
5317
5318 if(pal)
5319 {
5320 get_bw(imagepal,black,white);
5321
5322 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5323 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5324 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5325 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5326 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5327 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5328 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5329 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5330 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5331 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5332 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5333 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5334 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5335 gui_bg_color=jwin_pal[jcBOX];
5336 gui_fg_color=jwin_pal[jcBOXFG];
5337 jwin_set_colors(jwin_pal);
5338 }
5339 else
5340 {
5341 white=vc(15);
5342 black=vc(0);
5343
5344 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5345 gui_bg_color=jwin_pal[jcBOX];
5346 gui_fg_color=jwin_pal[jcBOXFG];
5347 jwin_set_colors(jwin_pal);
5348 }
5349
5350 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5351
5352 dopal=false;
5353 redraw=true;
5354 }
5355
5356 if(redraw)
5357 {
5358 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5359 }
5360 else
5361 {
5362 custom_vsync();
5363 }
5364
5365 if((f%8)==0)
5366 {
5367 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5368
5369 int selxl = selx* 2;
5370 int selyl = sely* 2;
5371 int w = 32;
5372
5373 if(f&8)
5374 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5375
5376 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5377 }
5378
5379 // SCRFIX();
5380 ++f;
5381
5382 }
5383 while(!done);
5384
5385 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5386 gui_bg_color=jwin_pal[jcBOX];
5387 gui_fg_color=jwin_pal[jcBOXFG];
5388 jwin_set_colors(jwin_pal);
5389
5390
5391 if(done==2)
5392 {
5393 go_tiles();
5394 saved=false;
5395
5396 // usetiles=true;
5397 for(int y=0; y<selheight; y++)
5398 {
5399 for(int x=0; x<selwidth; x++)
5400 {
5401 int temptile=tile+((TILES_PER_ROW*y)+x);
5402 int format=(bp==8) ? tf8Bit : tf4Bit;
5403
5404 if(newtilebuf[temptile].data!=NULL)
5405 free(newtilebuf[temptile].data);
5406
5407 newtilebuf[temptile].format=format;
5408 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5409
5410 if(newtilebuf[temptile].data==NULL)
5411 {
5412 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5413 break;
5414 }
5415
5416 for(int i=0; i<256; i++)
5417 {
5418 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5419 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5420 }
5421
5422 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5423 }
5424 }
5425 }
5426
5427 destroy_bitmap(screen3);
5428
5429 if(pal)
5430 zc_set_palette(RAMpal);
5431
5432 recolor=rcNone;
5433 calc_cset_reduce_table(imagepal, cs);
5434 register_blank_tiles();
5435 popup_zqdialog_end();
5436
5437 zq_allow_tile_draw_cache = false;
5438 }
5439
5440 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5441 bool tile_is_used(int32_t tile)
5442 {
5443 return used_tile_table[tile];
5444 }
5445 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5446 {
5447 draw_tiles(screen2, first, cs, f, true);
5448 }
5449 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5450 {
5451 clear_bitmap(dest);
5452 BITMAP *buf = create_bitmap_ex(8,16,16);
5453
5454 int32_t w = 16;
5455 int32_t h = 16;
5456
5457 if(large)
5458 {
5459 w *=2;
5460 h *=2;
5461 }
5462
5463 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5464 {
5465 int32_t x = (i%TILES_PER_ROW)<<4;
5466 int32_t y = (i/TILES_PER_ROW)<<4;
5467 int32_t l = 16;
5468
5469 if(large)
5470 {
5471 x*=2;
5472 y*=2;
5473 l*=2;
5474 }
5475
5476 l-=2;
5477
5478 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5479 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5480 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5481 {
5482 if(!true_empty) //Use pure color 0; no effects
5483 {
5484 if (InvalidBG == 2)
5485 {
5486 draw_checkerboard(dest, x, y, w);
5487 }
5488 else if(InvalidBG == 1)
5489 {
5490 for(int32_t dy=0; dy<=l+1; dy++)
5491 {
5492 for(int32_t dx=0; dx<=l+1; dx++)
5493 {
5494 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5495 }
5496 }
5497 }
5498 else
5499 {
5500 for(int32_t dy=0; dy<=l+1; dy++)
5501 {
5502 for(int32_t dx=0; dx<=l+1; dx++)
5503 {
5504 dest->line[dy+(y)][dx+(x)]=vc(0);
5505 }
5506 }
5507 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5508 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5509 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5510 }
5511 }
5512 }
5513 else
5514 {
5515 puttile16(buf,first+i,0,0,cs,0);
5516 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5517 }
5518
5519 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5520 {
5521 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5522 }
5523 }
5524
5525 destroy_bitmap(buf);
5526 }
5527
5528 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5529 {
5530 int32_t yofs=3;
5531 BITMAP *buf = create_bitmap_ex(8,16,16);
5532 int32_t mul = 2;
5533 FONT *tfont = get_zc_font(font_pfont);
5534
5535 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5536 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5537 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5538 tfont = get_zc_font(font_lfont_l);
5539
5540 // Copied tile and numbers
5541 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5542 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5543 if(copy>=0)
5544 {
5545 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5546 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5547
5548 if(copycnt>1)
5549 {
5550 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5551 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5552 }
5553 else
5554 {
5555 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5556 }
5557 }
5558 else // No tiles copied
5559 {
5560 if (InvalidBG == 2)
5561 {
5562 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5563 }
5564 else if(InvalidBG == 1)
5565 {
5566 for(int32_t dy=0; dy<16*mul; dy++)
5567 {
5568 for(int32_t dx=0; dx<16*mul; dx++)
5569 {
5570 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5571 }
5572 }
5573 }
5574 else
5575 {
5576 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5577 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5578 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5579 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5580 }
5581 }
5582
5583
5584 // Current tile
5585 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5586 puttile16(buf,tile,0,0,cs,0);
5587 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5588
5589 // Current selection mode
5590 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5591 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5592
5593 if(tile>tile2)
5594 {
5595 zc_swap(tile,tile2);
5596 }
5597
5598 char tbuf[8];
5599 tbuf[0]=0;
5600
5601 if(tile2!=tile)
5602 {
5603 sprintf(tbuf,"-%d",tile2);
5604 }
5605
5606 // Current tile and CSet text
5607 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5608 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5609 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5610
5611 FONT *tf = font;
5612 font = tfont;
5613
5614 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5615 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5616 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5617 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5618 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5619
5620 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5621 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5622 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5623 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5624
5625 font = tf;
5626
5627 int32_t w = 640;
5628 int32_t h = 480;
5629 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5630 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5631 int32_t screen_xofs=window_xofs+6;
5632 int32_t screen_yofs=window_yofs+25;
5633
5634 custom_vsync();
5635 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5636 SCRFIX();
5637 destroy_bitmap(buf);
5638 }
5639
5640 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5641 {
5642 int32_t yofs=3;
5643 BITMAP *buf = create_bitmap_ex(8,16,16);
5644 int32_t mul = 2;
5645 FONT *tfont = get_zc_font(font_pfont);
5646
5647 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5648 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5649 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5650 tfont = get_zc_font(font_lfont_l);
5651
5652 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5653
5654 if(copy>=0)
5655 {
5656 puttile16(buf,copy,0,0,cs,flip);
5657 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5658 }
5659 else
5660 {
5661 if (InvalidBG == 2)
5662 {
5663 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5664 }
5665 else if(InvalidBG == 1)
5666 {
5667 for(int32_t dy=0; dy<16*mul; dy++)
5668 {
5669 for(int32_t dx=0; dx<16*mul; dx++)
5670 {
5671 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5672 }
5673 }
5674 }
5675 else
5676 {
5677 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5678 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5679 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5680 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5681 }
5682 }
5683
5684 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5685 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5686 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5687
5688 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5689 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5690
5691 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5692 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5693
5694 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5695 {
5696 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5697 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5698 }
5699
5700 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5701 puttile16(buf,tile,0,0, cs,
5702 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5703 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5704
5705 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5706 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5707 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5708 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5709
5710 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5711 {
5712 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5713 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5714 }
5715
5716 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5717 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5718 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5719 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5720
5721
5722 int32_t w = 640;
5723 int32_t h = 480;
5724 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5725 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5726 int32_t screen_xofs=window_xofs+6;
5727 int32_t screen_yofs=window_yofs+25;
5728
5729 custom_vsync();
5730 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5731 SCRFIX();
5732 destroy_bitmap(buf);
5733 }
5734 /*
5735 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5736 {
5737 buf[t].format=format;
5738 if (buf[t].data!=NULL)
5739 {
5740 free(buf[t].data);
5741 }
5742 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5743 if (buf[t].data==NULL)
5744 {
5745 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5746 }
5747 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5748 {
5749 buf[t].data[i]=0;
5750 }
5751 }
5752 */
5753
5754 int32_t hide_used()
5755 {
5756 show_only_unused_tiles ^= 1;
5757 return D_O_K;
5758 }
5759 int32_t hide_unused()
5760 {
5761 show_only_unused_tiles ^= 2;
5762 return D_O_K;
5763 }
5764 int32_t hide_blank()
5765 {
5766 show_only_unused_tiles ^= 4;
5767 return D_O_K;
5768 }
5769 int32_t hide_8bit_marker()
5770 {
5771 show_only_unused_tiles ^= 8;
5772 return D_O_K;
5773 }
5774
5775 enum
5776 {
5777 MENUID_SELTILE_VIEW_HIDE_USED,
5778 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5779 MENUID_SELTILE_VIEW_HIDE_BLANK,
5780 MENUID_SELTILE_VIEW_HIDE_8BIT,
5781 };
5782
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_view_menu
5783 45 {
5784
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5785
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5786
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5787
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5788 };
5789
5790 9 static std::function<void(int)> select_tile_color_depth_cb;
5791
5792 static void set_tile_color_depth_4()
5793 {
5794 select_tile_color_depth_cb(tf4Bit);
5795 }
5796 static void set_tile_color_depth_8()
5797 {
5798 select_tile_color_depth_cb(tf8Bit);
5799 }
5800 enum
5801 {
5802 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5803 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5804 };
5805
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_color_depth_menu
5806 27 {
5807
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5808
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5809 };
5810
5811 //returns the row the tile is in on its page
5812 int32_t tile_page_row(int32_t tile)
5813 {
5814 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5815 }
5816
5817 enum {ti_none, ti_encompass, ti_broken};
5818
5819 //striped check and striped selection
5820 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5821 {
5822 int32_t cmb_first = cmb.o_tile;
5823 int32_t cmb_last = cmb.o_tile;
5824 do
5825 {
5826 cmb_last = cmb.tile;
5827 animate(cmb, true);
5828 }
5829 while(cmb.tile != cmb.o_tile);
5830 reset_combo_animation(cmb);
5831 cmb_first += offset;
5832 cmb_last += offset;
5833
5834 if(cmb_first > selection_last || cmb_last < selection_first)
5835 return ti_none;
5836 if(cmb_first >= selection_first && cmb_last <= selection_last)
5837 return ti_encompass;
5838
5839 do
5840 {
5841 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5842 {
5843 reset_combo_animation(cmb);
5844 return ti_broken; //contained, but non-encompassing.
5845 }
5846 animate(cmb, true);
5847 }
5848 while(cmb.tile != cmb.o_tile);
5849 reset_combo_animation(cmb);
5850 return ti_none;
5851 }
5852 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5853 {
5854 // if selection is before or after check...
5855 if((check_first>selection_last)||(selection_first>check_last))
5856 {
5857 return ti_none;
5858 }
5859
5860 // if selection envelopes check
5861 if((selection_first<=check_first)&&(selection_last>=check_last))
5862 {
5863 return ti_encompass; //encompass
5864 }
5865
5866 //everything else is a break
5867 return ti_broken; //intersect
5868 }
5869
5870
5871
5872 //rectangular check and striped selection
5873 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5874 {
5875 int32_t ret1=-1, ret2=-1;
5876
5877 for(int32_t i=0; i<check_height; ++i)
5878 {
5879 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5880 int32_t check_last=check_first+check_width-1;
5881 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5882
5883 if(ret2==ti_broken)
5884 {
5885 return ti_broken;
5886 }
5887
5888 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5889 }
5890
5891 if(ret1==ti_encompass)
5892 {
5893 if((TILEROW(selection_first)<=check_top) &&
5894 (TILEROW(selection_last)>=(check_top+check_height-1)))
5895 {
5896 return ti_encompass;
5897 }
5898 else
5899 {
5900 return ti_broken;
5901 }
5902 }
5903
5904 return ti_none;
5905 }
5906
5907
5908 //striped check and rectangular selection
5909 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5910 {
5911 if(selection_width < TILES_PER_ROW)
5912 {
5913 int32_t cmb_first = cmb.o_tile;
5914 int32_t cmb_last = cmb.o_tile;
5915 do
5916 {
5917 cmb_last = cmb.tile;
5918 animate(cmb, true);
5919 }
5920 while(cmb.tile != cmb.o_tile);
5921 reset_combo_animation(cmb);
5922 cmb_first += offset;
5923 cmb_last += offset;
5924
5925 if((TILEROW(cmb_first)>=selection_top) &&
5926 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5927 (TILECOL(cmb_first)>=selection_left) &&
5928 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5929 {
5930 return ti_encompass;
5931 }
5932 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5933 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5934 {
5935 return ti_none;
5936 }
5937
5938 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5939 {
5940 int32_t firstcol = TILECOL(cmb_first);
5941 int32_t lastcol = TILECOL(cmb_last);
5942
5943 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5944 return ti_none;
5945 else //handle skip x
5946 {
5947 do
5948 {
5949 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5950 {
5951 reset_combo_animation(cmb);
5952 return ti_broken;
5953 }
5954 animate(cmb, true);
5955 }
5956 while(cmb.tile != cmb.o_tile);
5957 reset_combo_animation(cmb);
5958 return ti_none;
5959 }
5960 }
5961 else //multi-row combo...
5962 {
5963 int32_t row = TILEROW(cmb_first);
5964
5965 do
5966 {
5967 if(row < selection_top || row > selection_top+selection_height-1)
5968 {
5969 //This row isn't in the selection; skip to next row
5970 do
5971 {
5972 animate(cmb,true);
5973 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5974 }
5975 while(TILEROW(cmb.tile) == row);
5976 row = TILEROW(cmb.tile);
5977 continue;
5978 }
5979
5980 //This row IS in the selection; check each tile.
5981 do
5982 {
5983 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5984 {
5985 reset_combo_animation(cmb);
5986 return ti_broken;
5987 }
5988 animate(cmb, true);
5989 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5990 }
5991 while(TILEROW(cmb.tile) == row);
5992 row = TILEROW(cmb.tile);
5993 }
5994 while(cmb.tile != cmb.o_tile);
5995
5996 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
5997 }
5998 }
5999
6000 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
6001 }
6002 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6003 {
6004 if(selection_width < TILES_PER_ROW)
6005 {
6006 if((check_last-check_first+1<=selection_width) &&
6007 (TILEROW(check_first)>=selection_top) &&
6008 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6009 (TILECOL(check_first)>=selection_left) &&
6010 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6011 {
6012 return ti_encompass;
6013 }
6014 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6015 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6016 {
6017 return ti_none;
6018 }
6019
6020 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6021
6022 //one last base case: the strip we're interested in only lies along one row
6023 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6024 {
6025 int32_t cfcol = check_first%TILES_PER_ROW;
6026 int32_t clcol = check_last%TILES_PER_ROW;
6027
6028 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6029 return ti_none;
6030 else
6031 return ti_broken;
6032 }
6033 else
6034 {
6035 //recursively cut the strip into substrips which lie entirely on one row
6036 int32_t currow = check_first/TILES_PER_ROW;
6037 int32_t endrow = check_last/TILES_PER_ROW;
6038 int32_t accum = 0;
6039 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6040
6041 for(++currow; currow<endrow; currow++)
6042 {
6043 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6044 }
6045
6046 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6047
6048 if(accum > 0)
6049 return ti_broken;
6050
6051 return ti_none;
6052 }
6053 }
6054
6055 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6056 }
6057
6058 //rectangular check and rectangular selection
6059 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6060 {
6061 if((check_left>=selection_left) &&
6062 (check_left+check_width<=selection_left+selection_width) &&
6063 (check_top>=selection_top) &&
6064 (check_top+check_height<=selection_top+selection_height))
6065 {
6066 return ti_encompass;
6067 }
6068 else
6069 {
6070 for(int32_t i=check_top; i<check_top+check_height; ++i)
6071 {
6072 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6073 {
6074 return ti_broken;
6075 }
6076 }
6077 }
6078
6079 return ti_none;
6080 }
6081
6082
6083
6084
6085 static DIALOG move_textbox_list_dlg[] =
6086 {
6087 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6088 9 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6089 9 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6090 9 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6091 9 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6092 9 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6093 9 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6094 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6095 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6096 };
6097
6098 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6099 {
6100 char buf1[512] = {0};
6101 char buf2[512] = {0};
6102 large_dialog(move_textbox_list_dlg);
6103 DIALOG& tbox = move_textbox_list_dlg[3];
6104 {
6105 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6106 int indx = 0, word_indx = 0;
6107 for(char c : msg)
6108 {
6109 if(c == ' ' || c == '\n')
6110 word_indx = indx;
6111 buf1[indx++] = c;
6112 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6113 {
6114 buf1[word_indx] = 0;
6115 strcpy(buf2, msg.c_str()+word_indx+1);
6116 break;
6117 }
6118 }
6119 }
6120
6121 move_textbox_list_dlg[0].dp = (void*)title;
6122 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6123 move_textbox_list_dlg[1].dp = buf1;
6124 move_textbox_list_dlg[2].dp = buf2;
6125 tbox.dp = textbox;
6126 tbox.d2 = 0;
6127 auto tby = tbox.y;
6128 auto tbh = tbox.h;
6129 if(!buf2[0])
6130 {
6131 auto diff = move_textbox_list_dlg[2].h;
6132 tbox.y -= diff;
6133 tbox.h += diff;
6134 }
6135
6136 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6137 position_mouse_z(0);
6138 tbox.y = tby;
6139 tbox.h = tbh;
6140
6141 return ret == 4;
6142 }
6143
6144 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6145 {
6146 return a==0?b:a==1?c:d;
6147 }
6148
6149 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6150 {
6151 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6152 int i = ti_none;
6153 auto t = ref->getTile() + ref->offset();
6154
6155 if(combo_ref)
6156 {
6157 if(proc.rect)
6158 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6159 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6160 }
6161 else if(proc.rect)
6162 {
6163 if(ref->h > 1)
6164 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6165 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6166 }
6167 else
6168 {
6169 if(ref->h > 1)
6170 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6171 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6172 }
6173
6174 bool in = i != ti_none, out = i != ti_encompass;
6175 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6176 {
6177 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6178 if(proc.rect)
6179 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6180 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6181 if(i != ti_none)
6182 in = true;
6183 if(i != ti_encompass)
6184 out = true;
6185 }
6186 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6187
6188 if(i != ti_none && ref->getTile() != 0)
6189 {
6190 if(mode == Mode::CHECK_ALL)
6191 {
6192 move_refs.emplace_back(std::move(ref));
6193 return true;
6194 }
6195 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6196 {
6197 if(warning_flood || warning_list.tellp() >= 65000)
6198 {
6199 if(!warning_flood)
6200 warning_list << "...\n...\n...\nmany others";
6201 warning_flood = true;
6202 }
6203 else
6204 warning_list << ref->name << '\n';
6205 }
6206 else if(i==ti_encompass)
6207 {
6208 move_refs.emplace_back(std::move(ref));
6209 return true;
6210 }
6211 }
6212 return false;
6213 }
6214
6215 bool TileMoveList::check_prot()
6216 {
6217 if(!TileProtection)
6218 return true;
6219 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6220
6221 warning_flood = false;
6222 warning_list.clear();
6223
6224 return ret;
6225 }
6226
6227 void TileMoveList::add_diff(int diff)
6228 {
6229 for(auto& ref : move_refs)
6230 ref->addTile(diff);
6231 }
6232
6233 //from 'combo.h'
6234 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6235 {
6236 int i = ti_none;
6237 auto c = ref->getCombo();
6238
6239 if(ref->no_move)
6240 processed_combos[c] = true;
6241 else processed_combos[c]; //inserts element if does not exist
6242 i = move_intersection_ss(c, c, proc._first, proc._last);
6243
6244 if(i != ti_none && ref->getCombo() != 0)
6245 {
6246 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6247 {
6248 if(ComboProtection)
6249 {
6250 if(warning_flood || warning_list.tellp() >= 65000)
6251 {
6252 if(!warning_flood)
6253 warning_list << "...\n...\n...\nmany others";
6254 warning_flood = true;
6255 }
6256 else
6257 warning_list << ref->name << '\n';
6258 }
6259 }
6260 else if(i==ti_encompass)
6261 {
6262 move_refs.emplace_back(std::move(ref));
6263 return true;
6264 }
6265 }
6266 return false;
6267 }
6268
6269 bool ComboMoveList::check_prot()
6270 {
6271 if(!ComboProtection)
6272 return true;
6273 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6274 bool subset_header = false;
6275 for(int q = 0; q < 2; ++q)
6276 {
6277 bool is_dest = (q==1);
6278 if(!is_dest && !source_process)
6279 continue;
6280 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6281 for(auto it = subset.begin(); it != subset.end();)
6282 {
6283 auto s = *it;
6284 if(warning_flood || warning_list.tellp() >= 65000)
6285 {
6286 if(!warning_flood)
6287 warning_list << "...\n...\n...\nmany others";
6288 warning_flood = true;
6289 break;
6290 }
6291 set<int> in_set, out_set;
6292 bool no_move = is_dest;
6293 for(int c : *s)
6294 {
6295 int i = move_intersection_ss(c, c, proc._first, proc._last);
6296 if(i != ti_none)
6297 in_set.insert(c);
6298 if(i != ti_encompass)
6299 out_set.insert(c);
6300 if(!no_move)
6301 {
6302 auto it = processed_combos.find(c);
6303 if(it != processed_combos.end() && it->second)
6304 no_move = true;
6305 }
6306 }
6307 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6308 if(i == ti_encompass && !no_move)
6309 {
6310 it = subset.erase(it);
6311 continue;
6312 }
6313 if(i == ti_none)
6314 {
6315 ++it;
6316 continue;
6317 }
6318
6319 if(!subset_header)
6320 {
6321 subset_header = true;
6322 warning_list << "===== Broken Relative Combo Groups =====\n";
6323 }
6324 bool comma = false;
6325 warning_list << "In(";
6326 for(int c : in_set)
6327 {
6328 if(comma)
6329 warning_list << ",";
6330 else comma = true;
6331 warning_list << c;
6332 }
6333 warning_list << "),Out(";
6334 comma = false;
6335 for(int c : out_set)
6336 {
6337 if(comma)
6338 warning_list << ",";
6339 else comma = true;
6340 warning_list << c;
6341 }
6342 warning_list << ")\n";
6343 it = subset.erase(it);
6344 }
6345 }
6346 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6347
6348 processed_combos.clear();
6349 warning_flood = false;
6350 warning_list.clear();
6351
6352 return ret;
6353 }
6354
6355 void ComboMoveList::add_diff(int diff)
6356 {
6357 for(auto& ref : move_refs)
6358 ref->addCombo(diff);
6359 }
6360
6361 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6362 {
6363 bool BSZ2 = get_qr(qr_BSZELDA);
6364 bool move = source_process.has_value();
6365 TileMoveUndo local_undo;
6366 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6367 auto& vec = storage.vec;
6368 storage.diff = diff;
6369 storage.state = false;
6370
6371 //Combos
6372 {
6373 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6374 dest_process, source_process, mode,
6375 move
6376 ? "The tiles used by the following combos will be partially cleared by the move."
6377 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6378 ));
6379 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6380 {
6381 auto& cmb = combobuf[q];
6382 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6383 : fmt::format(" ({})", cmb.label));
6384 movelist->add_combo(&cmb, lbl);
6385
6386 //type-specific
6387 char const* type_name = ZI.getComboTypeName(cmb.type);
6388 switch(cmb.type)
6389 {
6390 case cSPOTLIGHT:
6391 {
6392 if(!(cmb.usrflags & cflag1))
6393 break;
6394 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6395 break;
6396 }
6397 }
6398 }
6399 if(!every_proc && !movelist->check_prot())
6400 return false;
6401 }
6402 //Items
6403 {
6404 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6405 dest_process, source_process, mode,
6406 move
6407 ? "The tiles used by the following items will be partially cleared by the move."
6408 : "The tiles used by the following items will be partially or completely overwritten by this process."
6409 ));
6410 build_bii_list(false);
6411 for(int32_t u=0; u<MAXITEMS; u++)
6412 {
6413 auto id = bii[u].i;
6414 itemdata& itm = itemsbuf[id];
6415 if(itm.family == itype_bottle)
6416 {
6417 vector<std::tuple<int,int,int>> rects;
6418 auto fr = itm.frames;
6419 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6420 {
6421 bottletype const& bt = QMisc.bottle_types[q];
6422 if(bt.is_blank())
6423 continue;
6424 rects.emplace_back(fr+q*fr, fr, 1);
6425 }
6426 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6427 false, 0, 0, rects);
6428 }
6429 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6430 }
6431 if(!every_proc && !movelist->check_prot())
6432 return false;
6433 }
6434 //Weapon sprites
6435 {
6436 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6437 dest_process, source_process, mode,
6438 move
6439 ? "The tiles used by the following weapons will be partially cleared by the move."
6440 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6441 ));
6442 build_biw_list();
6443
6444 for(int32_t u=0; u<MAXWPNS; u++)
6445 {
6446 bool ignore_frames=false;
6447 int32_t m=0;
6448
6449 auto id = biw[u].i;
6450 auto& wpn = wpnsbuf[id];
6451
6452 switch(biw[u].i)
6453 {
6454 case wSWORD:
6455 case wWSWORD:
6456 case wMSWORD:
6457 case wXSWORD:
6458 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6459 break;
6460
6461 case wSWORDSLASH:
6462 case wWSWORDSLASH:
6463 case wMSWORDSLASH:
6464 case wXSWORDSLASH:
6465 m=4;
6466 break;
6467
6468 case iwMMeter:
6469 m=9;
6470 break;
6471
6472 case wBRANG:
6473 case wMBRANG:
6474 case wFBRANG:
6475 m=BSZ2?1:3;
6476 break;
6477
6478 case wBOOM:
6479 case wSBOOM:
6480 case ewBOOM:
6481 case ewSBOOM:
6482 ignore_frames=true;
6483 m=2;
6484 break;
6485
6486 case wWAND:
6487 m=1;
6488 break;
6489
6490 case wMAGIC:
6491 m=1;
6492 break;
6493
6494 case wARROW:
6495 case wSARROW:
6496 case wGARROW:
6497 case ewARROW:
6498 m=1;
6499 break;
6500
6501 case wHAMMER:
6502 m=8;
6503 break;
6504
6505 case wHSHEAD:
6506 m=1;
6507 break;
6508
6509 case wHSCHAIN_H:
6510 m=1;
6511 break;
6512
6513 case wHSCHAIN_V:
6514 m=1;
6515 break;
6516
6517 case wHSHANDLE:
6518 m=1;
6519 break;
6520
6521 case iwDeath:
6522 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6523 {
6524 ignore_frames = true;
6525 m=BSZ2?4:2;
6526 }
6527 break;
6528
6529 case iwSpawn:
6530 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6531 {
6532 ignore_frames = true;
6533 m=3;
6534 }
6535 break;
6536 }
6537
6538 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6539 1, fmt::format("{} {}", biw[u].s, id));
6540
6541 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6542 //...these can't be updated by a move.
6543 if((u==3)||(u==9))
6544 {
6545 static int32_t impact_tiles[2] = {54,54};
6546 auto& tile = impact_tiles[u==3 ? 0 : 1];
6547 tile = 54; //dummy tile, ensure it's correct
6548 movelist->add_tile(&tile, 2, 1,
6549 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6550 true);
6551 }
6552 }
6553 if(!every_proc && !movelist->check_prot())
6554 return false;
6555 }
6556 //Player sprites
6557 {
6558 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6559 dest_process, source_process, mode,
6560 move
6561 ? "The tiles used by the following player sprites will be partially cleared by the move."
6562 : "The tiles used by the following player sprites will be partially or completely overwritten by this process."
6563 ));
6564 {
6565 int32_t a_style=(zinit.heroAnimationStyle);
6566 #define ADD_PLAYER_SPRITE(ref_sprite, frames, name) \
6567 do \
6568 { \
6569 movelist->add_tile(&ref_sprite[spr_tile], \
6570 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6571 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6572 name, false, \
6573 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6574 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6575 } while(false)
6576 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6577
6578 for(int32_t i=0; i<4; ++i)
6579 {
6580 ADD_PLAYER_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6581 }
6582
6583 for(int32_t i=0; i<4; ++i)
6584 {
6585 ADD_PLAYER_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6586 }
6587
6588 for(int32_t i=0; i<4; ++i)
6589 {
6590 ADD_PLAYER_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6591 }
6592
6593 for(int32_t i=0; i<4; ++i)
6594 {
6595 ADD_PLAYER_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6596 }
6597
6598 for(int32_t i=0; i<2; ++i)
6599 {
6600 ADD_PLAYER_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6601 }
6602
6603 ADD_PLAYER_SPRITE(castingspr, 1, "Casting");
6604
6605 for(int32_t i=0; i<4; ++i)
6606 {
6607 ADD_PLAYER_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6608 }
6609
6610 for(int32_t i=0; i<4; ++i)
6611 {
6612 ADD_PLAYER_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6613 }
6614
6615 for(int32_t i=0; i<4; ++i)
6616 {
6617 ADD_PLAYER_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6618 }
6619
6620 for(int32_t i=0; i<2; ++i)
6621 {
6622 ADD_PLAYER_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6623 }
6624
6625 for(int32_t i=0; i<4; ++i)
6626 {
6627 ADD_PLAYER_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6628 }
6629
6630 for(int32_t i=0; i<4; ++i)
6631 {
6632 ADD_PLAYER_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6633 }
6634 for(int32_t i=0; i<4; ++i)
6635 {
6636 ADD_PLAYER_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6637 }
6638 for(int32_t i=0; i<4; ++i)
6639 {
6640 ADD_PLAYER_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6641 }
6642 for(int32_t i=0; i<4; ++i)
6643 {
6644 ADD_PLAYER_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6645 }
6646 for(int32_t i=0; i<4; ++i)
6647 {
6648 ADD_PLAYER_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6649 }
6650 for(int32_t i=0; i<4; ++i)
6651 {
6652 ADD_PLAYER_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6653 }
6654 for(int32_t i=0; i<4; ++i)
6655 {
6656 ADD_PLAYER_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6657 }
6658 for(int32_t i=0; i<4; ++i)
6659 {
6660 ADD_PLAYER_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6661 }
6662 //69
6663 for(int32_t i=0; i<4; ++i)
6664 {
6665 ADD_PLAYER_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6666 }
6667 //73
6668 for(int32_t i=0; i<4; ++i)
6669 {
6670 ADD_PLAYER_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6671 }
6672 //77
6673 for(int32_t i=0; i<4; ++i)
6674 {
6675 ADD_PLAYER_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6676 }
6677 //81
6678 for(int32_t i=0; i<4; ++i)
6679 {
6680 ADD_PLAYER_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6681 }
6682 //85
6683 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6684 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6685 ADD_PLAYER_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6686 for(int32_t i=0; i<4; ++i)
6687 {
6688 ADD_PLAYER_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6689 }
6690 //91
6691 }
6692 if(!every_proc && !movelist->check_prot())
6693 return false;
6694 }
6695 //Map Styles
6696 {
6697 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6698 dest_process, source_process, mode,
6699 move
6700 ? "The tiles used by the following map styles will be partially cleared by the move."
6701 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6702 ));
6703 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6704 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6705 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6706 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6707 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6708 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6709 if(!every_proc && !movelist->check_prot())
6710 return false;
6711 }
6712 //Game Icons
6713 {
6714 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6715 dest_process, source_process, mode,
6716 move
6717 ? "The tiles used by the following game icons will be partially cleared by the move."
6718 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6719 ));
6720 for(int32_t u=0; u<4; u++)
6721 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6722 if(!every_proc && !movelist->check_prot())
6723 return false;
6724 }
6725 //DMaps
6726 {
6727 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6728 dest_process, source_process, mode,
6729 move
6730 ? "The tiles used by the following dmaps will be partially cleared by the move."
6731 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6732 ));
6733 for(int32_t u=0; u<MAXDMAPS; u++)
6734 {
6735 auto& dm = DMaps[u];
6736 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6737 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6738 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6739 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6740 }
6741 if(!every_proc && !movelist->check_prot())
6742 return false;
6743 }
6744 //Enemies
6745 {
6746 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6747 dest_process, source_process, mode,
6748 move
6749 ? "The tiles used by the following enemies will be partially cleared by the move."
6750 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6751 ));
6752 build_bie_list(false);
6753 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6754 for(int u=0; u<eMAXGUYS; u++)
6755 {
6756 guydata& enemy=guysbuf[bie[u].i];
6757 bool darknut=false;
6758 int32_t gleeok=0;
6759
6760 if(enemy.family==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6761 darknut=true;
6762 else if(enemy.family==eeGLEEOK)
6763 {
6764 // Not certain this is the right thing to check...
6765 if(enemy.attributes[2] == 0)
6766 gleeok=1;
6767 else
6768 gleeok=2;
6769 }
6770
6771 // Dummied out enemies
6772 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6773 {
6774 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6775 {
6776 continue;
6777 }
6778 }
6779
6780 if(newtiles)
6781 {
6782 if(guysbuf[bie[u].i].e_tile==0)
6783 {
6784 continue;
6785 }
6786
6787 vector<std::tuple<int,int,int>> rects;
6788
6789 if(darknut)
6790 {
6791 rects.emplace_back(enemy.e_tile+6*TILES_PER_ROW, enemy.e_width, enemy.e_height);
6792 }
6793 else if(enemy.family==eeGANON)
6794 {
6795 rects.emplace_back(enemy.e_tile+2*TILES_PER_ROW, 20, 4);
6796 }
6797 else if(gleeok) //No idea if this is actually *RIGHT*, but I copied what was here before faithfully -Em
6798 {
6799 for(int32_t j=0; j<4; ++j)
6800 {
6801 rects.emplace_back(
6802 TILECOL(guysbuf[bie[u].i].e_tile+(gleeok>1?-4:8)) + TILES_PER_ROW*TILEROW(guysbuf[bie[u].i].e_tile+8)+(j<<1)+(gleeok>1?1:0),
6803 4, 1);
6804 }
6805 int32_t c=TILECOL(guysbuf[bie[u].i].e_tile)+(gleeok>1?-12:0);
6806 int32_t r=TILEROW(guysbuf[bie[u].i].e_tile)+(gleeok>1?17:8);
6807 rects.emplace_back(c+TILES_PER_ROW*r, 20, 3);
6808 rects.emplace_back(c+TILES_PER_ROW*(r+3), 16, 6);
6809 }
6810 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6811 false, 0, 0, rects);
6812 }
6813 else
6814 {
6815 if(guysbuf[bie[u].i].tile==0)
6816 {
6817 continue;
6818 }
6819 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6820
6821 if(guysbuf[bie[u].i].s_tile!=0)
6822 {
6823 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6824 }
6825 }
6826 }
6827 if(!every_proc && !movelist->check_prot())
6828 return false;
6829 }
6830 //Subscreens
6831 {
6832 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6833 dest_process, source_process, mode,
6834 move
6835 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6836 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6837 ));
6838
6839 for(auto q = 0; q < subscreens_active.size(); ++q)
6840 {
6841 size_t indx = movelist->move_refs.size();
6842 subscreens_active[q].collect_tiles(*movelist.get());
6843 for(; indx < movelist->move_refs.size(); ++indx)
6844 {
6845 auto& ref = movelist->move_refs[indx];
6846 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6847 }
6848 }
6849 for(auto q = 0; q < subscreens_passive.size(); ++q)
6850 {
6851 size_t indx = movelist->move_refs.size();
6852 subscreens_passive[q].collect_tiles(*movelist.get());
6853 for(; indx < movelist->move_refs.size(); ++indx)
6854 {
6855 auto& ref = movelist->move_refs[indx];
6856 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6857 }
6858 }
6859 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6860 {
6861 size_t indx = movelist->move_refs.size();
6862 subscreens_overlay[q].collect_tiles(*movelist.get());
6863 for(; indx < movelist->move_refs.size(); ++indx)
6864 {
6865 auto& ref = movelist->move_refs[indx];
6866 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6867 }
6868 }
6869 if(!every_proc && !movelist->check_prot())
6870 return false;
6871 }
6872 //Strings
6873 {
6874 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6875 dest_process, source_process, mode,
6876 move
6877 ? "The tiles used by the following strings will be partially cleared by the move."
6878 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6879 ));
6880 for(size_t q = 0; q < msg_count; ++q)
6881 {
6882 MsgStr& str = MsgStrings[q];
6883 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6884 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6885 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(str.s,100)));
6886 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6887 fmt::format("{} (Port.): '{}'", q, util::snip(str.s,100)));
6888 }
6889 if(!every_proc && !movelist->check_prot())
6890 return false;
6891 }
6892
6893 if(source_process) //Apply the 'diff' value to all moved tiles
6894 storage.redo();
6895 if(every_proc)
6896 for(auto &list : vec)
6897 for(auto &ref : list->move_refs)
6898 ref->forEach(every_proc);
6899 return true;
6900 }
6901 bool handle_tile_move(TileMoveProcess dest_process)
6902 {
6903 return _handle_tile_move(dest_process, nullopt, 0);
6904 }
6905 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6906 {
6907 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6908 }
6909 void for_every_used_tile(std::function<void(int32_t)> proc)
6910 {
6911 reset_combo_animations();
6912 reset_combo_animations2();
6913 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6914 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6915 }
6916
6917 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6918 {
6919 bool BSZ2 = get_qr(qr_BSZELDA);
6920 bool move = source_process.has_value();
6921 ComboMoveUndo local_undo;
6922 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
6923 auto& vec = storage.vec;
6924 auto& combo_links = storage.combo_links;
6925 storage.diff = diff;
6926 storage.state = false;
6927 //Combo relative links
6928 {
6929 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6930 {
6931 newcombo& cmb = combobuf[q];
6932 if(cmb.trigchange)
6933 combo_links.add_to(q, q+cmb.trigchange);
6934 bool next = cmb.flag == mfSECRETSNEXT;
6935 switch(cmb.type)
6936 {
6937 case cPOUND:
6938 case cLOCKBLOCK: case cLOCKBLOCK2:
6939 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
6940 case cCHEST: case cCHEST2:
6941 case cLOCKEDCHEST: case cLOCKEDCHEST2:
6942 case cBOSSCHEST: case cBOSSCHEST2:
6943 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
6944 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
6945 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
6946 case cTALLGRASSNEXT: case cCRUMBLE:
6947 next = true;
6948 break;
6949 case cCSWITCH: case cCSWITCHBLOCK:
6950 combo_links.add_to(q, q+cmb.attributes[0]);
6951 break;
6952 case cLIGHTTARGET:
6953 if(cmb.usrflags & cflag1)
6954 combo_links.add_to(q, q-1);
6955 else next = true;
6956 break;
6957 case cSTEPSFX:
6958 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
6959 next = true;
6960 break;
6961 }
6962 if(next)
6963 combo_links.add_to(q, q+1);
6964 }
6965 }
6966
6967 //This function is expensive! Any optimizations possible should be made. -Em
6968
6969 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
6970 #define ADDC(ptr, ...) \
6971 if(*ptr) movelist->add_combo(ptr, __VA_ARGS__);
6972 #define ADDC_10k(ptr, ...) \
6973 if(*ptr) movelist->add_combo_10k(ptr, __VA_ARGS__);
6974 //Combos
6975 {
6976 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
6977 combo_links, dest_process, source_process,
6978 move
6979 ? "The combos used by the following combos will be partially cleared by the move."
6980 : "The combos used by the following combos will be partially or completely overwritten by this process."
6981 ));
6982 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6983 {
6984 newcombo& cmb = combobuf[q];
6985 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
6986 : fmt::format(" ({})", cmb.label));
6987 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
6988 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
6989 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
6990 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
6991
6992 //type-specific
6993 char const* type_name = ZI.getComboTypeName(cmb.type);
6994 switch(cmb.type)
6995 {
6996 case cLOCKEDCHEST: case cBOSSCHEST:
6997 if(cmb.usrflags & cflag13)
6998 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
6999 [[fallthrough]];
7000 case cCHEST:
7001 if(cmb.usrflags & cflag13)
7002 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7003 break;
7004 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7005 if(cmb.usrflags & cflag13)
7006 {
7007 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7008 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7009 }
7010 break;
7011 case cSIGNPOST:
7012 if(cmb.usrflags & cflag13)
7013 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7014 break;
7015 case cBUTTONPROMPT:
7016 if(cmb.usrflags & cflag13)
7017 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7018 break;
7019 }
7020 }
7021
7022 if(!movelist->check_prot())
7023 return false;
7024 }
7025 //Door Combo Sets
7026 {
7027 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7028 combo_links, dest_process, source_process,
7029 move
7030 ? "The combos used by the following screens will be partially cleared by the move."
7031 : "The combos used by the following screens will be partially or completely overwritten by this process."
7032 ));
7033 static const char* door_names[9] = {
7034 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7035 };
7036 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7037 {
7038 auto& dcs = DoorComboSets[i];
7039 for(int32_t j=0; j<9; j++)
7040 {
7041 if(j<4)
7042 {
7043 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, dcs.name, j));
7044
7045 if(j<3)
7046 {
7047 if(j<2)
7048 {
7049 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, dcs.name, j));
7050 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, dcs.name, j));
7051 }
7052 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, dcs.name, j));
7053 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, dcs.name, j));
7054 }
7055 }
7056
7057 for(int32_t k=0; k<6; k++)
7058 {
7059 if(k<4)
7060 {
7061 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, dcs.name, door_names[j], k));
7062 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, dcs.name, door_names[j], k));
7063 }
7064
7065 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, dcs.name, door_names[j], k));
7066 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, dcs.name, door_names[j], k));
7067 }
7068 }
7069 }
7070
7071 if(!movelist->check_prot())
7072 return false;
7073 }
7074 //Combo Pools
7075 {
7076 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7077 combo_links, dest_process, source_process,
7078 move
7079 ? "The combos used by the following combo pools will be partially cleared by the move."
7080 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7081 ));
7082 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7083 {
7084 combo_pool& pool = combo_pools[q];
7085 int idx = 0;
7086 for(cpool_entry& cp : pool.combos)
7087 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7088 }
7089
7090 if(!movelist->check_prot())
7091 return false;
7092 }
7093 //Auto Combos
7094 {
7095 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7096 combo_links, dest_process, source_process,
7097 move
7098 ? "The combos used by the following autocombos will be partially cleared by the move."
7099 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7100 ));
7101 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7102 {
7103 combo_auto& cauto = combo_autos[q];
7104 int idx = 0;
7105 for (autocombo_entry& ac : cauto.combos)
7106 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7107 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7108 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7109 }
7110
7111 if(!movelist->check_prot())
7112 return false;
7113 }
7114 //Combo Aliases
7115 {
7116 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7117 combo_links, dest_process, source_process,
7118 move
7119 ? "The combos used by the following aliases will be partially cleared by the move."
7120 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7121 ));
7122 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7123 {
7124 //dimensions are 1 less than you would expect -DD
7125 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7126
7127 for(int32_t j=0; j<count; j++)
7128 {
7129 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7130 }
7131 }
7132
7133 if(!movelist->check_prot())
7134 return false;
7135 }
7136 //Favorite Combos
7137 {
7138 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7139 combo_links, dest_process, source_process,
7140 move
7141 ? "The combos used by the following favorite combos will be partially cleared by the move."
7142 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7143 ));
7144 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7145 {
7146 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7147 continue;
7148 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7149 }
7150
7151 if(!movelist->check_prot())
7152 return false;
7153 }
7154 //Bottle Shops
7155 {
7156 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7157 combo_links, dest_process, source_process,
7158 move
7159 ? "The combos used by the following bottle shops will be partially cleared by the move."
7160 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7161 ));
7162 for(auto q = 0; q < 256; ++q)
7163 for(auto p = 0; p < 3; ++p)
7164 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7165
7166 if(!movelist->check_prot())
7167 return false;
7168 }
7169 //Screens //EXPENSIVE! DO THIS LAST!
7170 {
7171 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7172 combo_links, dest_process, source_process,
7173 move
7174 ? "The combos used by the following screens will be partially cleared by the move."
7175 : "The combos used by the following screens will be partially or completely overwritten by this process."
7176 ));
7177
7178 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7179 {
7180 for(int32_t j=0; j<MAPSCRS; j++)
7181 {
7182 mapscr& scr = TheMaps[i*MAPSCRS+j];
7183
7184 if(!(scr.valid&mVALID))
7185 continue;
7186
7187 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7188 for(int32_t k=0; k<176; k++)
7189 ADDC(&scr.data[k], fmt::format("{}x{:02X} - Pos {}", i, j, k));
7190
7191 for(int32_t k=0; k<128; k++)
7192 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7193
7194 word maxffc = scr.numFFC();
7195 for(word k=0; k<maxffc; k++)
7196 {
7197 ffcdata& ffc = scr.ffcs[k];
7198 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7199 }
7200 }
7201 }
7202
7203 if(!movelist->check_prot())
7204 return false;
7205 }
7206 if(source_process) //Apply the 'diff' value to all moved combos
7207 storage.redo();
7208 return true;
7209 }
7210
7211 bool handle_combo_move(ComboMoveProcess dest_process)
7212 {
7213 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7214 }
7215 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7216 {
7217 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7218 }
7219 void register_used_tiles()
7220 {
7221 memset(used_tile_table, 0, sizeof(used_tile_table));
7222 for_every_used_tile([&](int tile)
7223 {
7224 used_tile_table[tile] = true;
7225 });
7226 }
7227
7228 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7229 {
7230 bool ctrl=(CHECK_CTRL_CMD);
7231 bool copied=false;
7232 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7233
7234 if(copied)
7235 {
7236 saved=false;
7237 }
7238
7239 return copied;
7240 }
7241
7242 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7243 {
7244 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7245 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7246
7247 // if tile>tile2 then swap them
7248 if(tile>tile2)
7249 {
7250 zc_swap(tile, tile2);
7251 }
7252
7253 // alt=copy from right
7254 // shift=copy from bottom
7255
7256 int32_t copies=copycnt;
7257 int32_t dest_first=tile;
7258 int32_t dest_last=tile2;
7259 int32_t src_first=copy;
7260 int32_t src_last=copy+copies-1;
7261
7262 int32_t dest_top=0;
7263 int32_t dest_bottom=0;
7264 int32_t src_top=0;
7265 int32_t src_bottom=0;
7266 int32_t src_left=0, src_right=0;
7267 int32_t src_width=0, src_height=0;
7268 int32_t dest_left=0, dest_right=0;
7269 int32_t dest_width=0, dest_height=0;
7270 int32_t rows=0, cols=0;
7271
7272 if(rect)
7273 {
7274 dest_top=TILEROW(dest_first);
7275 dest_bottom=TILEROW(dest_last);
7276 src_top=TILEROW(src_first);
7277 src_bottom=TILEROW(src_last);
7278
7279 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7280 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7281 src_first=(src_top * TILES_PER_ROW)+src_left;
7282 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7283
7284 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7285 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7286 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7287 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7288
7289 //if no dest range set, then set one
7290 if((dest_first==dest_last)&&(src_first!=src_last))
7291 {
7292 if(alt)
7293 {
7294 dest_left=dest_right-(src_right-src_left);
7295 }
7296 else
7297 {
7298 dest_right=dest_left+(src_right-src_left);
7299 }
7300
7301 if(shift)
7302 {
7303 dest_top=dest_bottom-(src_bottom-src_top);
7304 }
7305 else
7306 {
7307 dest_bottom=dest_top+(src_bottom-src_top);
7308 }
7309
7310 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7311 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7312 }
7313 else
7314 {
7315 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7316 {
7317 if(alt) //copy from right tile instead of left
7318 {
7319 src_left=src_right-(dest_right-dest_left);
7320 }
7321 else //copy from left tile
7322 {
7323 src_right=src_left+(dest_right-dest_left);
7324 }
7325 }
7326 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7327 {
7328 if(alt) //copy from right tile instead of left
7329 {
7330 dest_left=dest_right-(src_right-src_left);
7331 }
7332 else //copy from left tile
7333 {
7334 dest_right=dest_left+(src_right-src_left);
7335 }
7336 }
7337
7338 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7339 {
7340 if(shift) //copy from bottom tile instead of top
7341 {
7342 src_top=src_bottom-(dest_bottom-dest_top);
7343 }
7344 else //copy from top tile
7345 {
7346 src_bottom=src_top+(dest_bottom-dest_top);
7347 }
7348 }
7349 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7350 {
7351 if(shift) //copy from bottom tile instead of top
7352 {
7353 dest_top=dest_bottom-(src_bottom-src_top);
7354 }
7355 else //copy from top tile
7356 {
7357 dest_bottom=dest_top+(src_bottom-src_top);
7358 }
7359 }
7360
7361 src_first=(src_top * TILES_PER_ROW)+src_left;
7362 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7363 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7364 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7365 }
7366
7367 cols=src_right-src_left+1;
7368 rows=src_bottom-src_top+1;
7369
7370 dest_width=dest_right-dest_left+1;
7371 dest_height=dest_bottom-dest_top+1;
7372 src_width=src_right-src_left+1;
7373 src_height=src_bottom-src_top+1;
7374
7375 }
7376 else //!rect
7377 {
7378 //if no dest range set, then set one
7379 if((dest_first==dest_last)&&(src_first!=src_last))
7380 {
7381 if(alt)
7382 {
7383 dest_first=dest_last-(src_last-src_first);
7384 }
7385 else
7386 {
7387 dest_last=dest_first+(src_last-src_first);
7388 }
7389 }
7390 else
7391 {
7392 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7393 {
7394 if(alt) //copy from last tile instead of first
7395 {
7396 src_first=src_last-(dest_last-dest_first);
7397 }
7398 else //copy from first tile
7399 {
7400 src_last=src_first+(dest_last-dest_first);
7401 }
7402 }
7403 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7404 {
7405 if(alt) //copy from last tile instead of first
7406 {
7407 dest_first=dest_last-(src_last-src_first);
7408 }
7409 else //copy from first tile
7410 {
7411 dest_last=dest_first+(src_last-src_first);
7412 }
7413 }
7414 }
7415
7416 copies=dest_last-dest_first+1;
7417 }
7418
7419
7420
7421 char buf2[80], buf3[80], buf4[80];
7422 sprintf(buf2, " ");
7423 sprintf(buf3, " ");
7424 sprintf(buf4, " ");
7425
7426 // warn if range extends beyond last tile
7427 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7428
7429 if(dest_last>=NEWMAXTILES)
7430 {
7431 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7432 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7433 return false;
7434 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7435 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7436 // {
7437 // return false;
7438 // }
7439 }
7440
7441
7442 TileMoveUndo on_undo;
7443 // Overwrite warnings
7444 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7445 if(move)
7446 {
7447 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7448 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7449 return false;
7450 }
7451 else
7452 {
7453 if(!handle_tile_move(dest))
7454 return false;
7455 }
7456 // copy tiles and delete if needed (move)
7457
7458 {
7459 go_tiles();
7460
7461 int32_t diff=dest_first-src_first;
7462
7463 if(rect)
7464 {
7465 for(int32_t r=0; r<rows; ++r)
7466 {
7467 for(int32_t c=0; c<cols; ++c)
7468 {
7469 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7470 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7471
7472 if(dt>=NEWMAXTILES)
7473 continue;
7474
7475 overlay_tile(newtilebuf,dt,st,cs,backwards);
7476
7477 }
7478 }
7479 }
7480 else
7481 {
7482 for(int32_t c=0; c<copies; ++c)
7483 {
7484 int32_t dt=(dest_first+c);
7485 int32_t st=(src_first+c);
7486
7487 if(dt>=NEWMAXTILES)
7488 continue;
7489
7490 overlay_tile(newtilebuf,dt,st,cs,backwards);
7491
7492 if(move)
7493 {
7494 if(st<dest_first||st>(dest_first+c-1))
7495 reset_tile(newtilebuf, st, tf4Bit);
7496 }
7497 }
7498 }
7499 }
7500
7501 //now that tiles have moved, fix these buffers -DD
7502 register_blank_tiles();
7503 register_used_tiles();
7504
7505 if(move)
7506 last_tile_move_list = std::move(on_undo);
7507 return true;
7508 }
7509 //
7510 bool do_movetile_united(tile_move_data const& tmd)
7511 {
7512 char buf2[80], buf3[80], buf4[80];
7513 sprintf(buf2, " ");
7514 sprintf(buf3, " ");
7515 sprintf(buf4, " ");
7516
7517 // warn if range extends beyond last tile
7518 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7519
7520 if(tmd.dest_last>=NEWMAXTILES)
7521 {
7522 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7523 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7524 return false;
7525 }
7526
7527 TileMoveUndo on_undo;
7528 // Overwrite warnings
7529 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7530 if(tmd.move)
7531 {
7532 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7533 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7534 return false;
7535 }
7536 else
7537 {
7538 if(!handle_tile_move(dest))
7539 return false;
7540 }
7541
7542 // copy tiles and delete if needed (tmd.move)
7543 {
7544 go_tiles();
7545
7546 if(tmd.rect)
7547 {
7548 for(int32_t r=0; r<tmd.rows; ++r)
7549 {
7550 for(int32_t c=0; c<tmd.cols; ++c)
7551 {
7552 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7553 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7554
7555 if(dt>=NEWMAXTILES)
7556 continue;
7557
7558 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7559
7560 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7561 {
7562 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7563 }
7564
7565 if(tmd.move)
7566 {
7567 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7568 reset_tile(newtilebuf, st, tf4Bit);
7569 else
7570 {
7571 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7572 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7573 if(destLeft<=destRight)
7574 {
7575 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7576 reset_tile(newtilebuf, st, tf4Bit);
7577 }
7578 else // Wrapped around
7579 {
7580 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7581 reset_tile(newtilebuf, st, tf4Bit);
7582 }
7583 }
7584 }
7585 }
7586 }
7587 }
7588 else
7589 {
7590 for(int32_t c=0; c<tmd.copies; ++c)
7591 {
7592 int32_t dt=(tmd.dest_first+c);
7593 int32_t st=(tmd.src_first+c);
7594
7595 if(dt>=NEWMAXTILES)
7596 continue;
7597
7598 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7599
7600 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7601 {
7602 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7603 }
7604
7605 if(tmd.move)
7606 {
7607 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7608 reset_tile(newtilebuf, st, tf4Bit);
7609 }
7610 }
7611 }
7612 }
7613
7614 //now that tiles have moved, fix these buffers -DD
7615 register_blank_tiles();
7616 register_used_tiles();
7617
7618 if(tmd.move)
7619 last_tile_move_list = std::move(on_undo);
7620 return true;
7621 }
7622
7623 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7624 {
7625 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7626 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7627
7628 // if tile>tile2 then swap them
7629 if(tile>tile2)
7630 {
7631 zc_swap(tile, tile2);
7632 }
7633
7634 // alt=copy from right
7635 // shift=copy from bottom
7636 tile_move_data tmd;
7637
7638 tmd.copies=copycnt;
7639 tmd.dest_first=tile;
7640 tmd.dest_last=tile2;
7641 tmd.src_first=copy;
7642 tmd.src_last=copy+tmd.copies-1;
7643 tmd.rect = rect;
7644 tmd.move = move;
7645
7646 if(rect)
7647 {
7648 tmd.dest_top=TILEROW(tmd.dest_first);
7649 tmd.dest_bottom=TILEROW(tmd.dest_last);
7650 tmd.src_top=TILEROW(tmd.src_first);
7651 tmd.src_bottom=TILEROW(tmd.src_last);
7652
7653 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7654 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7655 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7656 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7657
7658 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7659 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7660 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7661 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7662
7663 //if no dest range set, then set one
7664 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7665 {
7666 if(alt)
7667 {
7668 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7669 }
7670 else
7671 {
7672 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7673 }
7674
7675 if(shift)
7676 {
7677 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7678 }
7679 else
7680 {
7681 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7682 }
7683
7684 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7685 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7686 }
7687 else
7688 {
7689 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7690 {
7691 if(alt) //copy from right tile instead of left
7692 {
7693 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7694 }
7695 else //copy from left tile
7696 {
7697 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7698 }
7699 }
7700 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7701 {
7702 if(alt) //copy from right tile instead of left
7703 {
7704 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7705 }
7706 else //copy from left tile
7707 {
7708 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7709 }
7710 }
7711
7712 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7713 {
7714 if(shift) //copy from bottom tile instead of top
7715 {
7716 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7717 }
7718 else //copy from top tile
7719 {
7720 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7721 }
7722 }
7723 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7724 {
7725 if(shift) //copy from bottom tile instead of top
7726 {
7727 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7728 }
7729 else //copy from top tile
7730 {
7731 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7732 }
7733 }
7734
7735 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7736 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7737 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7738 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7739 }
7740
7741 tmd.cols=tmd.src_right-tmd.src_left+1;
7742 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7743
7744 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7745 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7746 tmd.src_width=tmd.src_right-tmd.src_left+1;
7747 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7748
7749 }
7750 else //!rect
7751 {
7752 //if no dest range set, then set one
7753 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7754 {
7755 if(alt)
7756 {
7757 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7758 }
7759 else
7760 {
7761 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7762 }
7763 }
7764 else
7765 {
7766 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7767 {
7768 if(alt) //copy from last tile instead of first
7769 {
7770 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7771 }
7772 else //copy from first tile
7773 {
7774 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7775 }
7776 }
7777 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7778 {
7779 if(alt) //copy from last tile instead of first
7780 {
7781 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7782 }
7783 else //copy from first tile
7784 {
7785 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7786 }
7787 }
7788 }
7789
7790 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7791 }
7792
7793 return do_movetile_united(tmd);
7794 }
7795
7796 //
7797
7798 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7799 {
7800 assert(!move); //not implemented
7801
7802 // if tile>tile2 then swap them
7803 if(tile>tile2)
7804 {
7805 zc_swap(tile, tile2);
7806 }
7807
7808 tile_move_data tmd;
7809 tmd.copies=copycnt;
7810 tmd.dest_first=tile;
7811 tmd.dest_last=tile2;
7812 tmd.src_first=copy;
7813 tmd.src_last=copy+tmd.copies-1;
7814
7815
7816
7817 if(rect)
7818 {
7819 tmd.dest_top=TILEROW(tmd.dest_first);
7820 tmd.dest_bottom=TILEROW(tmd.dest_last);
7821 //tmd.src_top=TILEROW(tmd.src_first);
7822 //tmd.src_bottom=TILEROW(tmd.src_last);
7823
7824 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7825 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7826 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7827 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7828
7829 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7830 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7831 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7832 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7833
7834
7835
7836
7837 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7838 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7839
7840 tmd.cols=tmd.dest_width+1;
7841 tmd.rows=tmd.dest_height+1;
7842
7843 al_trace("tmd.rows: %d\n", tmd.rows);
7844 al_trace("tmd.cols: %d\n", tmd.cols);
7845
7846
7847 }
7848 else //!rect
7849 {
7850 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7851 }
7852
7853
7854
7855 char buf2[80], buf3[80], buf4[80];
7856 sprintf(buf2, " ");
7857 sprintf(buf3, " ");
7858 sprintf(buf4, " ");
7859
7860 // warn if range extends beyond last tile
7861 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7862
7863 if(tmd.dest_last>=NEWMAXTILES)
7864 {
7865 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7866 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7867 return false;
7868 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7869 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7870 // {
7871 // return false;
7872 // }
7873 }
7874
7875 TileMoveUndo on_undo;
7876 // Overwrite warnings
7877 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7878 if(tmd.move)
7879 {
7880 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7881 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7882 return false;
7883 }
7884 else
7885 {
7886 if(!handle_tile_move(dest))
7887 return false;
7888 }
7889
7890 // copy tiles and delete if needed (move)
7891
7892 {
7893 go_tiles();
7894
7895 int32_t diff=tmd.dest_first-tmd.src_first;
7896
7897 if(rect)
7898 {
7899 al_trace("floodfill, rect\n");
7900 al_trace("tmd.rows: %d\n", tmd.rows);
7901 al_trace("tmd.cols: %d\n", tmd.cols);
7902 for(int32_t r=0; r<tmd.rows; ++r)
7903 {
7904 for(int32_t c=0; c<tmd.cols; ++c)
7905 {
7906 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7907 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7908
7909 if(dt>=NEWMAXTILES)
7910 continue;
7911
7912 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7913
7914 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7915 {
7916 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7917 }
7918 }
7919 }
7920 }
7921 else
7922 {
7923 for(int32_t c=0; c<tmd.copies; ++c)
7924 {
7925 int32_t dt=(tmd.dest_first+c);
7926 int32_t st=(tmd.src_first+c);
7927
7928 if(dt>=NEWMAXTILES)
7929 continue;
7930
7931 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7932
7933 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7934 {
7935 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7936 }
7937
7938 }
7939 }
7940 }
7941
7942 //now that tiles have moved, fix these buffers -DD
7943 register_blank_tiles();
7944 register_used_tiles();
7945
7946 if(tmd.move)
7947 last_tile_move_list = std::move(on_undo);
7948 return true;
7949 }
7950 //
7951
7952 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7953 {
7954 al_trace("Floodfill Psste\n");
7955 bool ctrl=(CHECK_CTRL_CMD);
7956 bool copied=false;
7957 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
7958
7959 if(copied)
7960 {
7961 if(!ctrl)
7962 {
7963 copy=-1;
7964 tile2=tile;
7965 }
7966
7967 saved=false;
7968 }
7969
7970 return copied;
7971 }
7972
7973 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7974 {
7975 bool ctrl=(CHECK_CTRL_CMD);
7976 bool copied=false;
7977 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
7978
7979 if(copied)
7980 {
7981 if(!ctrl)
7982 {
7983 copy=-1;
7984 tile2=tile;
7985 }
7986
7987 saved=false;
7988 }
7989
7990 return copied;
7991 }
7992
7993 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
7994 {
7995 // if tile>tile2 then swap them
7996 if(tile>tile2)
7997 {
7998 zc_swap(tile, tile2);
7999 }
8000 int32_t src_top = TILEROW(tile);
8001 int32_t src_bottom = TILEROW(tile2);
8002 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8003 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8004 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8005 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8006
8007 int32_t src_width = src_right-src_left+1,
8008 src_height = src_bottom-src_top+1;
8009 int32_t dest_width = src_width, dest_height = src_height;
8010 zfix dest_rot = 0_zf;
8011 if(rotate)
8012 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8013 else
8014 ScaleTileDialog(&dest_width, &dest_height).show();
8015 if (rotate)
8016 {
8017 if (dest_rot == 0) return false;
8018 }
8019 else
8020 {
8021 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8022 }
8023 dest_width = vbound(dest_width, 1, 20);
8024 dest_height = vbound(dest_height, 1, 20);
8025
8026 int32_t dest_top = src_top;
8027 int32_t dest_bottom = src_top+dest_height-1;
8028 int32_t dest_left = src_left;
8029 int32_t dest_right = src_left+dest_width-1;
8030 int32_t dest_first = src_first;
8031 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8032
8033
8034 if(dest_last>=NEWMAXTILES)
8035 {
8036 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8037 return false;
8038 }
8039
8040 // Overwrite warnings
8041 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8042 return false;
8043
8044 //Do the rotate
8045 {
8046 go_tiles();
8047
8048 int32_t diff=dest_first-src_first;
8049 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8050 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8051 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8052 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8053 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8054 if (rotate)
8055 {
8056 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8057 }
8058 else
8059 {
8060 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8061 0, 0, destbmp->w, destbmp->h);
8062 }
8063 int32_t mhei = zc_max(src_height,dest_height),
8064 mwid = zc_max(src_width, dest_width);
8065 for(int32_t r=0; r<mhei; ++r)
8066 {
8067 for(int32_t c=0; c<mwid; ++c)
8068 {
8069 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8070
8071 if(dt>=NEWMAXTILES)
8072 continue;
8073 if(r < dest_height && c < dest_width)
8074 {
8075 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8076 }
8077 else reset_tile(newtilebuf, dt, tf4Bit);
8078 }
8079 }
8080 }
8081
8082 register_blank_tiles();
8083 register_used_tiles();
8084 return true;
8085 }
8086
8087 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8088 {
8089 //these 2 shouldn't be needed, but just to be safe...
8090 reset_combo_animations();
8091 reset_combo_animations2();
8092
8093 if(tile2<tile)
8094 {
8095 zc_swap(tile,tile2);
8096 }
8097
8098 auto first = tile;
8099 auto last = masscopy ? tile2 : first + copycnt-1;
8100 if(!handle_combo_move({first,last}))
8101 return;
8102
8103 if(!masscopy)
8104 {
8105 if(tile==copy)
8106 {
8107 copy=-1;
8108 tile2=tile;
8109 return;
8110 }
8111
8112 // go_combos(); // commented because caller does it for us
8113 //if copying to an earlier combo, copy from left to right
8114 //otherwise, copy from right to left
8115 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8116 {
8117 if(tile+t < MAXCOMBOS)
8118 {
8119 combobuf[tile+t]=combobuf[copy+t];
8120 }
8121 }
8122
8123 copy=-1;
8124 tile2=tile;
8125 saved=false;
8126 }
8127 else
8128 {
8129 // go_combos();
8130 int32_t src=copy, dest=tile;
8131
8132 do
8133 {
8134 combobuf[dest]=combobuf[src];
8135 ++src;
8136 ++dest;
8137
8138 if((src-copy)==copycnt) src=copy;
8139 }
8140 while(dest<=tile2);
8141
8142 copy=-1;
8143 tile2=tile;
8144 saved=false;
8145 }
8146
8147 setup_combo_animations();
8148 setup_combo_animations2();
8149 }
8150
8151 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8152 {
8153 reset_combo_animations();
8154 reset_combo_animations2();
8155 go_combos();
8156
8157 auto diff = cmd.tile - cmd.copy1;
8158 if(is_undoing)
8159 on_undo.undo();
8160 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8161 return false;
8162
8163 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8164 {
8165 if(cmd.tile+t < MAXCOMBOS)
8166 {
8167 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8168 clear_combo(cmd.copy1+t);
8169 }
8170 }
8171
8172 setup_combo_animations();
8173 setup_combo_animations2();
8174 saved=false;
8175 return true;
8176 }
8177
8178 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8179 {
8180 if(tile2<tile)
8181 {
8182 zc_swap(tile,tile2);
8183 }
8184
8185 if(tile==copy)
8186 {
8187 copy=-1;
8188 tile2=tile;
8189 return;
8190 }
8191
8192 combo_move_data cmd;
8193 cmd.tile = tile;
8194 cmd.tile2 = tile2;
8195 cmd.copy1 = copy;
8196 cmd.copycnt = copycnt;
8197
8198 ComboMoveUndo on_undo;
8199 if(!do_movecombo(cmd, on_undo))
8200 return;
8201 last_combo_move_list = std::move(on_undo);
8202 copy=-1;
8203 tile2=tile;
8204 }
8205
8206 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8207 {
8208 if(firsttile > lasttile)
8209 zc_swap(firsttile,lasttile);
8210 int32_t coldiff = 0;
8211 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8212 {
8213 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8214 firsttile-=coldiff;
8215 lasttile+=coldiff;
8216 }
8217 for(int32_t t=firsttile; t<=lasttile; ++t)
8218 if(!rect_sel ||
8219 ((TILECOL(t)>=TILECOL(firsttile)) &&
8220 (TILECOL(t)<=TILECOL(lasttile))))
8221 reset_tile(newtilebuf, t, tf4Bit);
8222 saved=false;
8223 register_blank_tiles();
8224 }
8225
8226 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8227 {
8228 char buf[40];
8229
8230 if(tile==tile2)
8231 {
8232 sprintf(buf,"Delete tile %d?",tile);
8233 }
8234 else
8235 {
8236 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8237 }
8238
8239 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8240 {
8241 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8242
8243 go_tiles();
8244
8245 //if copying to an earlier tile, copy from left to right
8246 //otherwise, copy from right to left
8247 do_delete_tiles(firsttile, lasttile, rect_sel);
8248
8249 tile=tile2=zc_min(tile,tile2);
8250 saved=false;
8251 register_blank_tiles();
8252 }
8253 }
8254
8255 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8256 {
8257 byte buf[256];
8258 go_tiles();
8259
8260 unpack_tile(newtilebuf, dest, 0, false);
8261
8262 for(int32_t i=0; i<256; i++)
8263 buf[i] = unpackbuf[i];
8264
8265 unpack_tile(newtilebuf, src, 0, false);
8266
8267 if(newtilebuf[src].format>tf4Bit)
8268 {
8269 cs=0;
8270 }
8271
8272 cs &= 15;
8273 cs <<= CSET_SHFT;
8274
8275 for(int32_t i=0; i<256; i++)
8276 {
8277 if(backwards)
8278 {
8279 if(!buf[i])
8280 {
8281 buf[i] = unpackbuf[i]+cs;
8282 }
8283 }
8284 else
8285 {
8286 if(unpackbuf[i])
8287 {
8288 buf[i] = unpackbuf[i]+cs;
8289 }
8290 }
8291 }
8292
8293 pack_tile(newtilebuf, buf,dest);
8294 saved=false;
8295 }
8296
8297 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8298 {
8299 //byte buf[256];
8300 go_tiles();
8301
8302 if(!rect_sel)
8303 {
8304 for(int32_t d=dest1; d <= dest2; ++d)
8305 {
8306 /*unpack_tile(newtilebuf, d, 0, false);
8307
8308 for(int32_t i=0; i<256; i++)
8309 {
8310 if(!backwards)
8311 {
8312 if(!buf[i])
8313 {
8314 buf[i] = unpackbuf[i] + cs;
8315 }
8316 }
8317 else
8318 {
8319 if(unpackbuf[i])
8320 {
8321 buf[i] = unpackbuf[i] + cs;
8322 }
8323 }
8324 }
8325
8326 pack_tile(newtilebuf, buf,d);
8327 */
8328
8329 overlay_tile(newtilebuf,d,src,cs,backwards);
8330
8331 if(!blank_tile_table[src])
8332 {
8333 blank_tile_table[d]=false;
8334 }
8335 }
8336 }
8337 else
8338 {
8339 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8340 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8341 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8342 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8343 int32_t d=0;
8344
8345 for(int32_t j=cmin; j<=cmax; ++j)
8346 {
8347 for(int32_t k=rmin; k<=rmax; ++k)
8348 {
8349 d=j+TILES_PER_ROW*k;
8350 /*unpack_tile(newtilebuf, d, 0, false);
8351
8352 for(int32_t i=0; i<256; i++)
8353 {
8354 if(!backwards)
8355 {
8356 if(!buf[i])
8357 {
8358 buf[i] = unpackbuf[i] + cs;
8359 }
8360 }
8361 else
8362 {
8363 if(unpackbuf[i])
8364 {
8365 buf[i] = unpackbuf[i] + cs;
8366 }
8367 }
8368 }
8369
8370 pack_tile(newtilebuf, buf,d);
8371 */
8372
8373 overlay_tile(newtilebuf,d,src,cs,backwards);
8374
8375 if(!blank_tile_table[src])
8376 {
8377 blank_tile_table[d]=false;
8378 }
8379 }
8380 }
8381 }
8382
8383 return;
8384 }
8385
8386 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8387 {
8388 tile+=s;
8389 bound(tile,0,NEWMAXTILES-1);
8390
8391 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8392 tile2 = tile;
8393
8394 first = tile - (tile%TILES_PER_PAGE);
8395 }
8396
8397 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8398 {
8399 int32_t cst;
8400
8401 switch(bp2)
8402 {
8403 case tf4Bit:
8404 switch(newtilebuf[t].format)
8405 {
8406 case tf4Bit:
8407 //already in the right format
8408 break;
8409
8410 case tf8Bit:
8411 unpack_tile(newtilebuf, t, 0, true);
8412
8413 if(alt) //reduce
8414 {
8415 for(int32_t i=0; i<256; i++)
8416 {
8417 if(!shift||unpackbuf[i]!=0)
8418 {
8419 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8420 }
8421 }
8422 }
8423 else //truncate
8424 {
8425 for(int32_t i=0; i<256; i++)
8426 {
8427 unpackbuf[i]&=15;
8428 }
8429 }
8430
8431 reset_tile(newtilebuf, t, tf4Bit);
8432 pack_tile(newtilebuf, unpackbuf, t);
8433 break;
8434 }
8435
8436 break;
8437
8438 case tf8Bit:
8439 switch(newtilebuf[t].format)
8440 {
8441 case tf4Bit:
8442 unpack_tile(newtilebuf, t, 0, true);
8443 cst = cs&15;
8444 cst <<= CSET_SHFT;
8445
8446 for(int32_t i=0; i<256; i++)
8447 {
8448 if(!shift||unpackbuf[i]!=0)
8449 {
8450 unpackbuf[i]+=cst;
8451 }
8452 }
8453
8454 reset_tile(newtilebuf, t, tf8Bit);
8455 pack_tile(newtilebuf, unpackbuf, t);
8456 break;
8457
8458 case tf8Bit:
8459 //already in the right format
8460 break;
8461 }
8462
8463 break;
8464 }
8465 }
8466
8467 static DIALOG create_relational_tiles_dlg[] =
8468 {
8469 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8470 9 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8471 9 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8472 9 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8473 9 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8474 9 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8475 9 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8476 9 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8477 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8478 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8479 };
8480
8481 void draw_tile_list_window()
8482 {
8483 int32_t w = 640;
8484 int32_t h = 480;
8485
8486 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8487 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8488 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8489 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8490
8491 FONT *oldfont = font;
8492 font = get_zc_font(font_lfont);
8493 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8494 font=oldfont;
8495 return;
8496 }
8497
8498 void show_blank_tile(int32_t t)
8499 {
8500 char tbuf[80], tbuf2[80], tbuf3[80];
8501 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8502 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8503 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8504 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8505 }
8506
8507 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8508 {
8509 int num_bits;
8510 if (format == tf4Bit)
8511 num_bits = 4;
8512 else if (format == tf8Bit)
8513 num_bits = 8;
8514 else assert(false);
8515
8516 char buf[80];
8517 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8518
8519 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8520 {
8521 go_tiles();
8522 saved=false;
8523
8524 if(format == tf4Bit)
8525 {
8526 memset(cset_reduce_table, 0, 256);
8527 memset(col_diff,0,3*128);
8528 calc_cset_reduce_table(RAMpal, cs);
8529 }
8530
8531 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8532
8533 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8534 {
8535 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8536 firsttile-=coldiff;
8537 lasttile+=coldiff;
8538 }
8539
8540 for(int32_t t=firsttile; t<=lasttile; t++)
8541 if(!rect_sel ||
8542 ((TILECOL(t)>=TILECOL(firsttile)) &&
8543 (TILECOL(t)<=TILECOL(lasttile))))
8544 convert_tile(t, format, cs, shift, alt);
8545
8546 tile=tile2=zc_min(tile,tile2);
8547 }
8548 }
8549
8550
8551 int32_t readtilefile(PACKFILE *f)
8552 {
8553 dword section_version=0;
8554 dword section_cversion=0;
8555 int32_t zversion = 0;
8556 int32_t zbuild = 0;
8557
8558 if(!p_igetl(&zversion,f))
8559 {
8560 return 0;
8561 }
8562 if(!p_igetl(&zbuild,f))
8563 {
8564 return 0;
8565 }
8566 if(!p_igetw(&section_version,f))
8567 {
8568 return 0;
8569 }
8570 if(!p_igetw(&section_cversion,f))
8571 {
8572 return 0;
8573 }
8574 al_trace("readoneweapon section_version: %d\n", section_version);
8575 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8576
8577 if ( zversion > ZELDA_VERSION )
8578 {
8579 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8580 return 0;
8581 }
8582
8583 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8584 {
8585 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8586 return 0;
8587
8588 }
8589 else
8590 {
8591 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8592 }
8593
8594 int32_t index = 0;
8595 int32_t count = 0;
8596
8597 //tile id
8598 if(!p_igetl(&index,f))
8599 {
8600 return 0;
8601 }
8602 al_trace("Reading tile: index(%d)\n", index);
8603
8604 //tile count
8605 if(!p_igetl(&count,f))
8606 {
8607 return 0;
8608 }
8609 al_trace("Reading tile: count(%d)\n", count);
8610
8611
8612
8613
8614 for ( int32_t tilect = 0; tilect < count; tilect++ )
8615 {
8616 byte *temp_tile = new byte[tilesize(tf32Bit)];
8617 byte format=tf4Bit;
8618 memset(temp_tile, 0, tilesize(tf32Bit));
8619 if(!p_getc(&format,f))
8620 {
8621 delete[] temp_tile;
8622 return 0;
8623 }
8624
8625
8626 if(!pfread(temp_tile,tilesize(format),f))
8627 {
8628 delete[] temp_tile;
8629 return 0;
8630 }
8631
8632 reset_tile(newtilebuf, index+(tilect), format);
8633 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8634 delete[] temp_tile;
8635 }
8636
8637
8638 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8639
8640 register_blank_tiles();
8641 register_used_tiles();
8642
8643 return 1;
8644
8645 }
8646
8647 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8648 {
8649 dword section_version=0;
8650 dword section_cversion=0;
8651 int32_t zversion = 0;
8652 int32_t zbuild = 0;
8653
8654 if(!p_igetl(&zversion,f))
8655 {
8656 return 0;
8657 }
8658 if(!p_igetl(&zbuild,f))
8659 {
8660 return 0;
8661 }
8662 if(!p_igetw(&section_version,f))
8663 {
8664 return 0;
8665 }
8666 if(!p_igetw(&section_cversion,f))
8667 {
8668 return 0;
8669 }
8670 al_trace("readoneweapon section_version: %d\n", section_version);
8671 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8672
8673 if ( zversion > ZELDA_VERSION )
8674 {
8675 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8676 return 0;
8677 }
8678
8679 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8680 {
8681 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8682 return 0;
8683
8684 }
8685 else
8686 {
8687 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8688 }
8689
8690 int32_t index = 0;
8691 int32_t count = 0;
8692
8693 //tile id
8694 if(!p_igetl(&index,f))
8695 {
8696 return 0;
8697 }
8698 al_trace("Reading tile: index(%d)\n", index);
8699
8700 //tile count
8701 if(!p_igetl(&count,f))
8702 {
8703 return 0;
8704 }
8705 al_trace("Reading tile: count(%d)\n", count);
8706
8707
8708 for ( int32_t tilect = 0; tilect < count; tilect++ )
8709 {
8710 byte *temp_tile = new byte[tilesize(tf32Bit)];
8711 byte format=tf4Bit;
8712 memset(temp_tile, 0, tilesize(tf32Bit));
8713 if(!p_getc(&format,f))
8714 {
8715 delete[] temp_tile;
8716 return 0;
8717 }
8718
8719
8720 if(!pfread(temp_tile,tilesize(format),f))
8721 {
8722 delete[] temp_tile;
8723 return 0;
8724 }
8725
8726 reset_tile(newtilebuf, start+(tilect), format);
8727 if ( skip )
8728 {
8729 if ( (start+(tilect)) < skip )
8730 {
8731 delete[] temp_tile;
8732 continue;
8733 }
8734
8735 }
8736 if ( start+(tilect) < NEWMAXTILES )
8737 {
8738 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8739 }
8740 delete[] temp_tile;
8741
8742 }
8743
8744
8745 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8746
8747 register_blank_tiles();
8748 register_used_tiles();
8749
8750 return 1;
8751
8752 }
8753
8754
8755 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8756 {
8757 dword section_version=0;
8758 dword section_cversion=0;
8759 int32_t zversion = 0;
8760 int32_t zbuild = 0;
8761
8762 if(!p_igetl(&zversion,f))
8763 {
8764 return 0;
8765 }
8766 if(!p_igetl(&zbuild,f))
8767 {
8768 return 0;
8769 }
8770 if(!p_igetw(&section_version,f))
8771 {
8772 return 0;
8773 }
8774 if(!p_igetw(&section_cversion,f))
8775 {
8776 return 0;
8777 }
8778 al_trace("readoneweapon section_version: %d\n", section_version);
8779 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8780
8781 if ( zversion > ZELDA_VERSION )
8782 {
8783 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8784 return 0;
8785 }
8786
8787 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8788 {
8789 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8790 return 0;
8791
8792 }
8793 else
8794 {
8795 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8796 }
8797
8798 int32_t index = 0;
8799 int32_t count = 0;
8800
8801 //tile id
8802 if(!p_igetl(&index,f))
8803 {
8804 return 0;
8805 }
8806 al_trace("Reading tile: index(%d)\n", index);
8807
8808 //tile count
8809 if(!p_igetl(&count,f))
8810 {
8811 return 0;
8812 }
8813 al_trace("Reading tile: count(%d)\n", count);
8814
8815
8816
8817
8818 for ( int32_t tilect = 0; tilect < count; tilect++ )
8819 {
8820 byte *temp_tile = new byte[tilesize(tf32Bit)];
8821 byte format=tf4Bit;
8822 memset(temp_tile, 0, tilesize(tf32Bit));
8823
8824 if(!p_getc(&format,f))
8825 {
8826 delete[] temp_tile;
8827 return 0;
8828 }
8829
8830
8831 if(!pfread(temp_tile,tilesize(format),f))
8832 {
8833 delete[] temp_tile;
8834 return 0;
8835 }
8836
8837 reset_tile(newtilebuf, start+(tilect), format);
8838 if ( start+(tilect) < NEWMAXTILES )
8839 {
8840 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8841 }
8842 delete[] temp_tile;
8843 }
8844
8845
8846 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8847
8848 register_blank_tiles();
8849 register_used_tiles();
8850
8851 return 1;
8852
8853 }
8854 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8855 {
8856 dword section_version=V_TILES;
8857 dword section_cversion=CV_TILES;
8858 int32_t zversion = ZELDA_VERSION;
8859 int32_t zbuild = VERSION_BUILD;
8860
8861 if(!p_iputl(zversion,f))
8862 {
8863 return 0;
8864 }
8865 if(!p_iputl(zbuild,f))
8866 {
8867 return 0;
8868 }
8869 if(!p_iputw(section_version,f))
8870 {
8871 return 0;
8872 }
8873
8874 if(!p_iputw(section_cversion,f))
8875 {
8876 return 0;
8877 }
8878
8879 //start tile id
8880 if(!p_iputl(index,f))
8881 {
8882 return 0;
8883 }
8884
8885 //count
8886 if(!p_iputl(count,f))
8887 {
8888 return 0;
8889 }
8890
8891 for ( int32_t tilect = 0; tilect < count; tilect++ )
8892 {
8893 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8894 {
8895 return 0;
8896 }
8897 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8898 {
8899 return 0;
8900 }
8901 }
8902
8903 return 1;
8904
8905 }
8906
8907 static int32_t _selected_tile=-1, _selected_tcset=-1;
8908 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8909 {
8910 popup_zqdialog_start();
8911 reset_combo_animations();
8912 reset_combo_animations2();
8913 bound(tile,0,NEWMAXTILES-1);
8914 ex=exnow;
8915 int32_t done=0;
8916 int32_t oflip=flip;
8917 int32_t otile=tile;
8918 int32_t ocs=cs;
8919 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
8920 int32_t copy=-1;
8921 int32_t tile2=tile,copycnt=0;
8922 int32_t tile_clicked=-1;
8923 bool rect_sel=true;
8924 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
8925 position_mouse_z(0);
8926
8927 go();
8928
8929 register_used_tiles();
8930 int32_t w = 640;
8931 int32_t h = 480;
8932 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8933 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8934 int32_t screen_xofs=window_xofs+6;
8935 int32_t screen_yofs=window_yofs+25;
8936 int32_t panel_yofs=3;
8937 int32_t mul = 2;
8938 FONT *tfont = get_zc_font(font_lfont_l);
8939
8940 draw_tile_list_window();
8941 int32_t f=0;
8942 draw_tiles(first,cs,f);
8943
8944 if(type==0)
8945 {
8946 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
8947 }
8948 else
8949 {
8950 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
8951 }
8952
8953 go_tiles();
8954
8955 while(gui_mouse_b())
8956 {
8957 /* do nothing */
8958 rest(1);
8959 }
8960
8961 bool bdown=false;
8962
8963 #define FOREACH_START(_t) \
8964 { \
8965 int32_t _first, _last; \
8966 if(is_rect) \
8967 { \
8968 _first=top*TILES_PER_ROW+left; \
8969 _last=_first+rows*TILES_PER_ROW|+columns-1; \
8970 } \
8971 else \
8972 { \
8973 _first=zc_min(tile, tile2); \
8974 _last=zc_max(tile, tile2); \
8975 } \
8976 for(int32_t _t=_first; _t<=_last; _t++) \
8977 { \
8978 if(is_rect) \
8979 { \
8980 int32_t row=TILEROW(_t); \
8981 if(row<top || row>=top+rows) \
8982 continue; \
8983 int32_t col=TILECOL(_t); \
8984 if(col<left || col>=left+columns) \
8985 continue; \
8986 } \
8987
8988 #define FOREACH_END\
8989 } \
8990 }
8991
8992 bool did_snap = false;
8993 int otl = tile, otl2 = tile2;
8994 do
8995 {
8996 HANDLE_CLOSE_ZQDLG();
8997 if(exiting_program) break;
8998 rest(4);
8999 int32_t top=TILEROW(zc_min(tile, tile2));
9000 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9001 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9002 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9003 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9004 bool redraw=false;
9005
9006 if(mouse_z!=0)
9007 {
9008 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9009 position_mouse_z(0);
9010 redraw=true;
9011 }
9012
9013 if(keypressed())
9014 {
9015 switch(readkey()>>8)
9016 {
9017 case KEY_ENTER_PAD:
9018 case KEY_ENTER:
9019 done=2;
9020 break;
9021
9022 case KEY_ESC:
9023 done=1;
9024 break;
9025
9026 case KEY_F1:
9027 onHelp();
9028 break;
9029
9030 case KEY_EQUALS:
9031 case KEY_PLUS_PAD:
9032 {
9033 if(CHECK_CTRL_CMD ||
9034 key[KEY_ALT] || key[KEY_ALTGR])
9035 {
9036 FOREACH_START(t)
9037 if(key[KEY_ALT] || key[KEY_ALTGR])
9038 shift_tile_colors(t, 16, false);
9039 else
9040 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9041 FOREACH_END
9042
9043 register_blank_tiles();
9044 }
9045 else if(edit_cs)
9046 cs = (cs<13) ? cs+1:0;
9047
9048 redraw=true;
9049 break;
9050 }
9051
9052 case KEY_Z:
9053 case KEY_F12:
9054 {
9055 if(!did_snap)
9056 {
9057 //Export tile page as screenshot
9058 PALETTE temppal;
9059 get_palette(temppal);
9060 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9061 draw_tiles(tempbmp,first,cs,f,false,true);
9062 save_bitmap(getSnapName(), tempbmp, RAMpal);
9063 destroy_bitmap(tempbmp);
9064
9065 redraw = true;
9066 did_snap = true;
9067 }
9068 break;
9069 }
9070
9071 case KEY_S:
9072 {
9073 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9074 break;
9075 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9076 if(!f) break;
9077 al_trace("Saving tile: %d\n", tile);
9078 writetilefile(f,tile,1);
9079 pack_fclose(f);
9080 break;
9081 }
9082 case KEY_L:
9083 {
9084 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9085 break;
9086 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9087 if(!f) break;
9088 al_trace("Saving tile: %d\n", tile);
9089 if (!readtilefile(f))
9090 {
9091 al_trace("Could not read from .ztile packfile %s\n", temppath);
9092 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9093 }
9094 else
9095 {
9096 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9097 }
9098
9099 pack_fclose(f);
9100 //register_blank_tiles();
9101 //register_used_tiles();
9102 redraw=true;
9103 break;
9104 }
9105 case KEY_MINUS:
9106 case KEY_MINUS_PAD:
9107 {
9108 if(CHECK_CTRL_CMD ||
9109 key[KEY_ALT] || key[KEY_ALTGR])
9110 {
9111 FOREACH_START(t)
9112 if(key[KEY_ALT] || key[KEY_ALTGR])
9113 shift_tile_colors(t, -16, false);
9114 else
9115 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9116 FOREACH_END
9117
9118 register_blank_tiles();
9119 }
9120 else if(edit_cs)
9121 cs = (cs>0) ? cs-1:13;
9122
9123 redraw=true;
9124 break;
9125 }
9126
9127 case KEY_UP:
9128 {
9129 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9130 {
9131 case 3: //ALT and CTRL
9132 case 2: //ALT
9133 if(is_rect)
9134 {
9135 saved=false;
9136 go_slide_tiles(columns, rows, top, left);
9137 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9138 bool same = true;
9139
9140 for(int32_t d=0; d<columns; d++)
9141 {
9142 for(int32_t s=0; s<rows; s++)
9143 {
9144 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9145
9146 if(newtilebuf[t].format!=bitcheck) same = false;
9147 }
9148 }
9149
9150 if(!same) break;
9151
9152 // This used to do something. Too lazy to remove.
9153 // Can probably remove the above "same" check too.
9154 bitcheck = 2;
9155
9156 for(int32_t c=0; c<columns; c++)
9157 {
9158 for(int32_t r=0; r<rows; r++)
9159 {
9160 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9161 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9162 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9163
9164 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9165 {
9166 if(pixelrow==15*bitcheck)
9167 {
9168 int32_t srctile=temptile+TILES_PER_ROW;
9169 if(srctile>=NEWMAXTILES)
9170 srctile-=rows*TILES_PER_ROW;
9171 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9172 }
9173
9174 *dest_pixelrow=*src_pixelrow;
9175 dest_pixelrow++;
9176 src_pixelrow++;
9177 }
9178 }
9179
9180 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9181
9182 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9183 {
9184 if((CHECK_CTRL_CMD))
9185 {
9186 *dest_pixelrow=0;
9187 }
9188 else
9189 {
9190 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9191 *dest_pixelrow=*src_pixelrow;
9192 }
9193 }
9194 }
9195 }
9196
9197 register_blank_tiles();
9198 redraw=true;
9199 break;
9200
9201 case 1: //CTRL
9202 case 0: //None
9203 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9204 redraw=true;
9205
9206 default: //Others
9207 break;
9208 }
9209 }
9210 break;
9211
9212 case KEY_DOWN:
9213 {
9214 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9215 {
9216 case 3: //ALT and CTRL
9217 case 2: //ALT
9218 if(is_rect)
9219 {
9220 saved=false;
9221 go_slide_tiles(columns, rows, top, left);
9222 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9223 bool same = true;
9224
9225 for(int32_t c=0; c<columns; c++)
9226 {
9227 for(int32_t r=0; r<rows; r++)
9228 {
9229 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9230
9231 if(newtilebuf[t].format!=bitcheck) same = false;
9232 }
9233 }
9234
9235 if(!same) break;
9236
9237 // This used to do something. Too lazy to remove.
9238 // Can probably remove the above "same" check too.
9239 bitcheck = 2;
9240
9241 for(int32_t c=0; c<columns; c++)
9242 {
9243 for(int32_t r=rows-1; r>=0; r--)
9244 {
9245 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9246 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9247 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9248
9249 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9250 {
9251 if(pixelrow<bitcheck)
9252 {
9253 int32_t srctile=temptile-TILES_PER_ROW;
9254 if(srctile<0)
9255 srctile+=rows*TILES_PER_ROW;
9256 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9257 *dest_pixelrow=*tempsrc;
9258 //*dest_pixelrow=0;
9259 }
9260 else
9261 {
9262 *dest_pixelrow=*src_pixelrow;
9263 }
9264
9265 dest_pixelrow--;
9266 src_pixelrow--;
9267 }
9268 }
9269
9270 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9271 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9272
9273 for(int32_t b=0; b<bitcheck; b++)
9274 {
9275 if((CHECK_CTRL_CMD))
9276 {
9277 *dest_pixelrow=0;
9278 }
9279 else
9280 {
9281 *dest_pixelrow=*src_pixelrow;
9282 }
9283
9284 dest_pixelrow++;
9285 src_pixelrow++;
9286 }
9287 }
9288 }
9289
9290 register_blank_tiles();
9291 redraw=true;
9292 break;
9293
9294 case 1: //CTRL
9295 case 0: //None
9296 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9297 redraw=true;
9298
9299 default: //Others
9300 break;
9301 }
9302 }
9303 break;
9304
9305 case KEY_LEFT:
9306 {
9307 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9308 {
9309 case 3: //ALT and CTRL
9310 case 2: //ALT
9311 if(is_rect)
9312 {
9313 saved=false;
9314 go_slide_tiles(columns, rows, top, left);
9315 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9316 bool same = true;
9317
9318 for(int32_t c=0; c<columns; c++)
9319 {
9320 for(int32_t r=0; r<rows; r++)
9321 {
9322 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9323
9324 if(newtilebuf[t].format!=bitcheck) same = false;
9325 }
9326 }
9327
9328 if(!same) break;
9329
9330 // This used to do something. Too lazy to remove.
9331 // Can probably remove the above "same" check too.
9332 bitcheck = 2;
9333
9334 for(int32_t r=0; r<rows; r++)
9335 {
9336 for(int32_t c=0; c<columns; c++)
9337 {
9338 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9339 byte *dest_pixelrow=(newtilebuf[temptile].data);
9340
9341 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9342 {
9343 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9344 {
9345 *dest_pixelrow=*(dest_pixelrow+1);
9346 dest_pixelrow++;
9347 }
9348
9349 if(c==columns-1)
9350 {
9351 if(!(CHECK_CTRL_CMD))
9352 {
9353 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9354 *dest_pixelrow=*tempsrc;
9355 }
9356 }
9357 else
9358
9359 {
9360 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9361 *dest_pixelrow=*tempsrc;
9362 }
9363
9364 dest_pixelrow++;
9365 }
9366 }
9367 }
9368
9369 register_blank_tiles();
9370 redraw=true;
9371 }
9372
9373 break;
9374
9375 case 1: //CTRL
9376 case 0: //None
9377 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9378 redraw=true;
9379
9380 default: //Others
9381 break;
9382 }
9383 }
9384 break;
9385
9386 case KEY_RIGHT:
9387 {
9388 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9389 {
9390 case 3: //ALT and CTRL
9391 case 2: //ALT
9392 if(is_rect)
9393 {
9394 saved=false;
9395 go_slide_tiles(columns, rows, top, left);
9396 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9397 bool same = true;
9398
9399 for(int32_t c=0; c<columns; c++)
9400 {
9401 for(int32_t r=0; r<rows; r++)
9402 {
9403 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9404
9405 if(newtilebuf[t].format!=bitcheck) same = false;
9406 }
9407 }
9408
9409 if(!same) break;
9410
9411 // This used to do something. Too lazy to remove.
9412 // Can probably remove the above "same" check too.
9413 bitcheck = 2;
9414
9415 for(int32_t r=0; r<rows; r++)
9416 {
9417 for(int32_t c=columns-1; c>=0; c--)
9418 {
9419 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9420 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9421
9422 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9423 {
9424 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9425 {
9426 *dest_pixelrow=*(dest_pixelrow-1);
9427 dest_pixelrow--;
9428 }
9429
9430 if(c==0)
9431 {
9432 if(!(CHECK_CTRL_CMD))
9433 {
9434 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9435 *dest_pixelrow=*tempsrc;
9436 }
9437 }
9438 else
9439 {
9440 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9441 *dest_pixelrow=*tempsrc;
9442 }
9443
9444 dest_pixelrow--;
9445 }
9446 }
9447 }
9448
9449 register_blank_tiles();
9450 redraw=true;
9451 }
9452
9453 break;
9454
9455 case 1: //CTRL
9456 case 0: //None
9457 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9458 redraw=true;
9459
9460 default: //Others
9461 break;
9462 }
9463 }
9464 break;
9465
9466 case KEY_PGUP:
9467 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9468 redraw=true;
9469 break;
9470
9471 case KEY_PGDN:
9472 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9473 redraw=true;
9474 break;
9475
9476 case KEY_HOME:
9477 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9478 redraw=true;
9479 break;
9480
9481 case KEY_END:
9482 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9483 redraw=true;
9484 break;
9485
9486 case KEY_P:
9487 {
9488 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9489
9490 if(whatPage >= 0)
9491 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9492
9493 break;
9494 }
9495
9496 case KEY_O:
9497 if(type==0 && copy>=0)
9498 {
9499 go_tiles();
9500
9501 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9502 {
9503 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9504 saved=false;
9505 }
9506 else
9507 {
9508 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9509 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9510 }
9511
9512 saved=false;
9513 redraw=true;
9514 }
9515
9516 break;
9517
9518 case KEY_E:
9519 if(type==0)
9520 {
9521 edit_tile(tile,flip,cs);
9522 draw_tile_list_window();
9523 redraw=true;
9524 }
9525
9526 break;
9527
9528 case KEY_G:
9529 if(type==0)
9530 {
9531 grab_tile(tile,cs);
9532 draw_tile_list_window();
9533 redraw=true;
9534 }
9535
9536 break;
9537
9538 case KEY_C:
9539 copy=zc_min(tile,tile2);
9540 copycnt=abs(tile-tile2)+1;
9541 redraw=true;
9542 break;
9543
9544 case KEY_X:
9545 if(type==2)
9546 {
9547 ex=(ex+1)%3;
9548 }
9549
9550 break;
9551
9552 //usetiles=true;
9553 case KEY_R:
9554 if(type==2)
9555 break;
9556 if(type==1)
9557 {
9558 flip = rotate_value(flip);
9559 redraw=true;
9560 break;
9561 }
9562
9563 go_tiles();
9564
9565 if(CHECK_CTRL_CMD)
9566 {
9567 bool go=false;
9568 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9569 go=true;
9570 else if(massRecolorSetup(cs))
9571 go=true;
9572
9573 if(go)
9574 {
9575 FOREACH_START(t)
9576 massRecolorApply(t);
9577 FOREACH_END
9578
9579 register_blank_tiles();
9580 }
9581 }
9582 else
9583 {
9584 FOREACH_START(t)
9585 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9586 FOREACH_END
9587 }
9588
9589 redraw=true;
9590 saved=false;
9591 break;
9592
9593 case KEY_SPACE:
9594 rect_sel=!rect_sel;
9595 copy=-1;
9596 redraw=true;
9597 break;
9598
9599 // case KEY_N: go_tiles(); normalize(tile,tile2,flip); flip=0; redraw=true; saved=false; usetiles=true; break;
9600 case KEY_H:
9601 flip^=1;
9602 go_tiles();
9603
9604 if(type==0)
9605 {
9606 normalize(tile,tile2,rect_sel,flip);
9607 flip=0;
9608 }
9609
9610 redraw=true;
9611 break;
9612
9613
9614 case KEY_V:
9615 if(copy==-1)
9616 {
9617 if(type!=2)
9618 {
9619 flip^=2;
9620 go_tiles();
9621
9622 if(type==0)
9623 {
9624 normalize(tile,tile2,rect_sel,flip);
9625 flip=0;
9626 }
9627 }
9628 }
9629 else
9630 {
9631 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9632 go_tiles();
9633 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9634 }
9635
9636 redraw=true;
9637 break;
9638
9639 case KEY_F:
9640 if(copy==-1)
9641 {
9642 break;
9643 }
9644 else
9645 {
9646 go_tiles();
9647 {
9648 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9649 }
9650 }
9651
9652 redraw=true;
9653 break;
9654
9655 case KEY_DEL:
9656 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9657 {
9658 bool warn = (rect_sel
9659 && ((tile/20)!=(tile2/20))
9660 && !(tile%20==0&&tile2%20==19));
9661 int32_t z=zc_min(tile,tile2);
9662 int32_t count = abs(tile-tile2) + 1;
9663 tile=z;
9664 tile2=NEWMAXTILES;
9665 copy = tile + count;
9666 copycnt = NEWMAXTILES-copy;
9667 char buf[64];
9668
9669 if(count>1)
9670 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9671 else
9672 sprintf(buf,"Remove tile %d?",tile);
9673
9674 AlertDialog("Remove Tiles", std::string(buf)
9675 +"\nThis will offset the tiles that follow!"
9676 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9677 [&](bool ret,bool)
9678 {
9679 if(ret)
9680 {
9681 go_tiles();
9682 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9683 {
9684 redraw=true;
9685 saved=false;
9686 }
9687 }
9688 }).show();
9689 }
9690 delete_tiles(tile,tile2,rect_sel);
9691 redraw=true;
9692 break;
9693
9694 case KEY_U:
9695 {
9696 if(CHECK_CTRL_CMD)
9697 {
9698 //Only toggle the first 2 bits!
9699 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9700 }
9701 else
9702 {
9703 comeback_tiles();
9704 }
9705
9706 redraw=true;
9707 }
9708 break;
9709
9710 case KEY_8:
9711 case KEY_8_PAD:
9712 hide_8bit_marker();
9713 break;
9714
9715 case KEY_I: //insert tiles
9716 if(type==0)
9717 {
9718 bool warn = (rect_sel
9719 && ((tile/20)!=(tile2/20))
9720 && !(tile%20==0&&tile2%20==19));
9721 int32_t z=zc_min(tile,tile2);
9722 int32_t count = abs(tile-tile2) + 1;
9723 tile=z;
9724 tile2=NEWMAXTILES;
9725 copy = tile + count;
9726 copycnt = NEWMAXTILES-copy;
9727
9728 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9729 {
9730 char buf[64];
9731
9732 if(count>1)
9733 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9734 else
9735 sprintf(buf,"Remove tile %d?",tile);
9736
9737 AlertDialog("Remove Tiles", std::string(buf)
9738 +"\nThis will offset the tiles that follow!"
9739 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9740 [&](bool ret,bool)
9741 {
9742 if(ret)
9743 {
9744 go_tiles();
9745 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9746 {
9747 redraw=true;
9748 saved=false;
9749 }
9750 }
9751 }).show();
9752 }
9753 else
9754 {
9755 char buf[64];
9756
9757 if(count>1)
9758 sprintf(buf,"Insert %d blank tiles?",count);
9759 else
9760 sprintf(buf,"Insert a blank tile?");
9761
9762 AlertDialog("Insert Tiles", std::string(buf)
9763 +"\nThis will offset the tiles that follow!"
9764 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9765 [&](bool ret,bool)
9766 {
9767 if(ret)
9768 {
9769 go_tiles();
9770 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9771 {
9772 redraw=true;
9773 saved=false;
9774 }
9775 }
9776 }).show();
9777 }
9778
9779 copy=-1;
9780 tile2=tile=z;
9781 }
9782 break;
9783 case KEY_M:
9784 if(type==0)
9785 {
9786 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9787 {
9788 go_tiles();
9789 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9790 saved=false;
9791 }
9792 else if(copy==-1)
9793 {
9794 // I don't know what this was supposed to be doing before.
9795 // It didn't work in anything like a sensible way.
9796 if(rect_sel)
9797 {
9798 make_combos_rect(top, left, rows, columns, cs);
9799 }
9800 else
9801 {
9802 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9803 }
9804 }
9805
9806 redraw=true;
9807 }
9808 break;
9809
9810 case KEY_D:
9811 {
9812 int32_t frames=1;
9813 char buf[80];
9814 sprintf(buf, "%d", frames);
9815 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9816 create_relational_tiles_dlg[2].dp=buf;
9817
9818 large_dialog(create_relational_tiles_dlg);
9819
9820 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9821
9822 if(ret==5)
9823 {
9824 frames=zc_max(atoi(buf),1);
9825 bool same = true;
9826 int32_t bitcheck=newtilebuf[tile].format;
9827
9828 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9829 {
9830 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9831 }
9832
9833 if(!same)
9834 {
9835 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9836 break;
9837 }
9838
9839 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9840 {
9841 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9842 break;
9843 }
9844
9845 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9846 {
9847 reset_tile(newtilebuf, tile+i, bitcheck);
9848 }
9849
9850 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9851 {
9852 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9853 {
9854 for(int32_t j=0; j<frames; ++j)
9855 {
9856 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9857 }
9858 }
9859 }
9860 else
9861 {
9862 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9863 {
9864 for(int32_t j=0; j<frames; ++j)
9865 {
9866 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9867 }
9868 }
9869 }
9870 }
9871 register_blank_tiles();
9872 register_used_tiles();
9873 redraw=true;
9874 saved=false;
9875 break;
9876 }
9877
9878 case KEY_B:
9879 {
9880 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9881 bool control=(CHECK_CTRL_CMD);
9882 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9883 int format = control ? tf4Bit : tf8Bit;
9884
9885 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9886 register_blank_tiles();
9887 }
9888 break;
9889 }
9890
9891 clear_keybuf();
9892 }
9893
9894 if(!(key[KEY_Z] || key[KEY_F12]))
9895 did_snap = false;
9896
9897 if(gui_mouse_b()&1)
9898 {
9899 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9900 {
9901 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9902 {
9903 done=1;
9904 }
9905 }
9906
9907 int32_t x=gui_mouse_x()-screen_xofs;
9908 int32_t y=gui_mouse_y()-screen_yofs;
9909
9910 if(y>=0 && y<208*mul)
9911 {
9912 x=zc_min(zc_max(x,0),(320*mul)-1);
9913 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9914
9915 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9916 {
9917 tile2=t;
9918 }
9919 else
9920 {
9921 tile=tile2=t;
9922 }
9923
9924 if(tile_clicked!=t)
9925 {
9926 dclick_status=DCLICK_NOT;
9927 }
9928 else if(dclick_status == DCLICK_AGAIN)
9929 {
9930 while(gui_mouse_b())
9931 {
9932 /* do nothing */
9933 rest(1);
9934 }
9935
9936 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
9937 {
9938 dclick_status=DCLICK_NOT;
9939 }
9940 else
9941 {
9942 if(type==0)
9943 {
9944 edit_tile(tile,flip,cs);
9945 draw_tile_list_window();
9946 redraw=true;
9947 }
9948 else
9949 {
9950 done=2;
9951 }
9952 }
9953 }
9954
9955 tile_clicked=t;
9956 }
9957 else if(x>300*mul && !bdown)
9958 {
9959 if(y<224*mul && first>0)
9960 {
9961 first-=TILES_PER_PAGE;
9962 redraw=true;
9963 }
9964
9965 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
9966 {
9967 first+=TILES_PER_PAGE;
9968 redraw=true;
9969 }
9970
9971 bdown=true;
9972 }
9973
9974 if(type==1||type==2)
9975 {
9976 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
9977 done=1;
9978
9979 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
9980 done=2;
9981 }
9982 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
9983 {
9984 rect_sel=!rect_sel;
9985 copy=-1;
9986 redraw=true;
9987 }
9988 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
9989 {
9990 FONT *tf = font;
9991 font = tfont;
9992
9993 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
9994 {
9995 font = tf;
9996 grab_tile(tile,cs);
9997 draw_tile_list_window();
9998 position_mouse_z(0);
9999 redraw=true;
10000 }
10001
10002 font = tf;
10003 }
10004 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10005 {
10006 FONT *tf = font;
10007 font = tfont;
10008
10009 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10010 {
10011 font = tf;
10012 edit_tile(tile,flip,cs);
10013 draw_tile_list_window();
10014 redraw=true;
10015 }
10016
10017 font = tf;
10018 }
10019 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10020 {
10021 FONT *tf = font;
10022 font = tfont;
10023
10024 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10025 {
10026 std::string initial_path = "tileset.png";
10027 if (strlen(datapath))
10028 initial_path = fmt::format("{}/{}", datapath, initial_path);
10029 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10030 {
10031 PALETTE temppal;
10032 get_palette(temppal);
10033 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10034 draw_tiles(tempbmp,first,cs,f,false,true);
10035 save_bitmap(temppath, tempbmp, RAMpal);
10036 destroy_bitmap(tempbmp);
10037 }
10038 }
10039
10040 font = tf;
10041 }
10042 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10043 {
10044 FONT *tf = font;
10045 font = tfont;
10046
10047 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10048 {
10049 if(massRecolorSetup(cs))
10050 {
10051 go_tiles();
10052
10053 FOREACH_START(t)
10054 massRecolorApply(t);
10055 FOREACH_END
10056
10057 register_blank_tiles();
10058 }
10059 }
10060
10061 font = tf;
10062 }
10063 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10064 {
10065 FONT *tf = font;
10066 font = tfont;
10067
10068 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10069 {
10070 done=1;
10071 }
10072
10073 font = tf;
10074 }
10075
10076 bdown=true;
10077 }
10078
10079 bool r_click = false;
10080
10081 if(gui_mouse_b()&2 && !bdown && type==0)
10082 {
10083 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10084 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10085
10086 if(y>=0 && y<208*mul)
10087 {
10088 x=zc_min(zc_max(x,0),(320*mul)-1);
10089 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10090
10091 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10092 tile=tile2=t;
10093 }
10094
10095 bdown = r_click = true;
10096 f=8;
10097 }
10098
10099 if(gui_mouse_b()==0)
10100 bdown=false;
10101
10102 position_mouse_z(0);
10103
10104 REDRAW:
10105
10106 if((f%8)==0 || InvalidBG == 1)
10107 redraw=true;
10108 if(otl != tile || otl2 != tile2)
10109 {
10110 otl = tile;
10111 otl2 = tile2;
10112 redraw = true;
10113 }
10114
10115 if(redraw)
10116 {
10117 draw_tiles(first,cs,f);
10118 }
10119 if(f&8)
10120 {
10121 if(rect_sel)
10122 {
10123 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10124 zc_min(TILECOL(tile),TILECOL(tile2));
10125 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10126 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10127 {
10128 if(i>=first && i<first+TILES_PER_PAGE &&
10129 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10130 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10131 {
10132 int32_t x=TILECOL(i)<<(5);
10133 int32_t y=TILEROW(i-first)<<(5);
10134 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10135 }
10136 }
10137 }
10138 else
10139 {
10140 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10141 {
10142 if(i>=first && i<first+TILES_PER_PAGE)
10143 {
10144 int32_t x=TILECOL(i)<<(5);
10145 int32_t y=TILEROW(i-first)<<(5);
10146 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10147 }
10148 }
10149 }
10150 }
10151
10152 if(type==0)
10153 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10154 else
10155 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10156
10157 if(type==2)
10158 {
10159 char cbuf[16];
10160 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10161 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10162 }
10163
10164 ++f;
10165
10166 if(r_click)
10167 {
10168 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10169 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10170 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10171 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10172
10173 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10174 if (newtilebuf[tile].format == tf8Bit)
10175 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10176 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10177 select_tile_color_depth_cb = [&](int format){
10178 if (newtilebuf[tile].format == format)
10179 return;
10180
10181 bool skip_prompt = true;
10182 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10183 };
10184
10185 NewMenu rcmenu
10186 {
10187 { "Copy", [&]()
10188 {
10189 copy = zc_min(tile,tile2);
10190 copycnt = abs(tile-tile2)+1;
10191 } },
10192 { "Paste", [&]()
10193 {
10194 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10195 if(saved) saved = !b;
10196 }, nullopt, copy < 0 },
10197 { "Move", [&]()
10198 {
10199 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10200 if(saved) saved = !b;
10201 }, nullopt, copy < 0 },
10202 { "Clear", [&]()
10203 {
10204 delete_tiles(tile, tile2, rect_sel);
10205 } },
10206 {},
10207 { "Edit", [&]()
10208 {
10209 edit_tile(tile, flip, cs);
10210 draw_tile_list_window();
10211 } },
10212 { "Grab", [&]()
10213 {
10214 grab_tile(tile, cs);
10215 draw_tile_list_window();
10216 position_mouse_z(0);
10217 } },
10218 { "Scale", [&]()
10219 {
10220 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10221 if(saved) saved = !b;
10222 }, nullopt, type != 0 },
10223 { "Angular Rotation", [&]()
10224 {
10225 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10226 if(saved) saved = !b;
10227 }, nullopt, type != 0 },
10228 { "Color Depth", &select_tile_color_depth_menu },
10229 {},
10230 { "Blank?", [&]()
10231 {
10232 show_blank_tile(tile);
10233 } },
10234 {},
10235 { "View ", &select_tile_view_menu },
10236 { "Overlay", [&]()
10237 {
10238 overlay_tile(newtilebuf, tile, copy, cs, 0);
10239 } },
10240 { "H-Flip", [&]()
10241 {
10242 flip ^= 1;
10243 go_tiles();
10244
10245 if(type == 0)
10246 {
10247 normalize(tile, tile2, rect_sel, flip);
10248 flip = 0;
10249 }
10250 } },
10251 { "V-Flip", [&]()
10252 {
10253 flip ^= 2;
10254 go_tiles();
10255
10256 if(type == 0)
10257 {
10258 normalize(tile, tile2, rect_sel, flip);
10259 flip = 0;
10260 }
10261 } },
10262 { "Create Combos", [&]()
10263 {
10264 if(rect_sel)
10265 make_combos_rect(top, left, rows, columns, cs);
10266 else
10267 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10268 }, nullopt, type != 0 },
10269 { "Insert", [&]()
10270 {
10271 bool warn = (rect_sel
10272 && ((tile/20)!=(tile2/20))
10273 && !(tile%20==0&&tile2%20==19));
10274 int32_t z = zc_min(tile, tile2);
10275 int32_t count = abs(tile-tile2) + 1;
10276 tile = z;
10277 tile2 = NEWMAXTILES;
10278 copy = tile + count;
10279 copycnt = NEWMAXTILES-copy;
10280
10281 string msg;
10282
10283 if(count>1)
10284 msg = fmt::format("Insert {} blank tiles?",count);
10285 else
10286 msg = "Insert a blank tile?";
10287
10288 AlertDialog("Insert Tiles", msg
10289 +"\nThis will offset the tiles that follow!"
10290 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10291 [&](bool ret,bool)
10292 {
10293 if(ret)
10294 {
10295 go_tiles();
10296 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10297 saved = false;
10298 }
10299 }).show();
10300
10301 copy=-1;
10302 tile2=tile=z;
10303 }, nullopt, type != 0 },
10304 { "Remove", [&]()
10305 {
10306 bool warn = (rect_sel
10307 && ((tile/20)!=(tile2/20))
10308 && !(tile%20==0&&tile2%20==19));
10309 int32_t z = zc_min(tile, tile2);
10310 int32_t count = abs(tile-tile2) + 1;
10311 tile = z;
10312 tile2 = NEWMAXTILES;
10313 copy = tile + count;
10314 copycnt = NEWMAXTILES-copy;
10315
10316 string msg;
10317
10318 if(count>1)
10319 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10320 else
10321 msg = fmt::format("Remove tile {}?", tile);
10322
10323 AlertDialog("Remove Tiles", msg
10324 +"\nThis will offset the tiles that follow!"
10325 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10326 [&](bool ret,bool)
10327 {
10328 if(ret)
10329 {
10330 go_tiles();
10331 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10332 saved = false;
10333 }
10334 }).show();
10335
10336 copy=-1;
10337 tile2=tile=z;
10338 }, nullopt, type != 0 },
10339 };
10340 rcmenu.pop(window_mouse_x(),window_mouse_y());
10341 redraw = true;
10342 r_click = false;
10343 goto REDRAW;
10344 }
10345 update_hw_screen();
10346 }
10347 while(!done);
10348
10349 while(gui_mouse_b())
10350 {
10351 /* do nothing */
10352 rest(1);
10353 }
10354
10355 comeback();
10356 register_blank_tiles();
10357 register_used_tiles();
10358 setup_combo_animations();
10359 setup_combo_animations2();
10360 int32_t ret = done-1;
10361 if(ret)
10362 {
10363 _selected_tile = tile;
10364 _selected_tcset = cs;
10365 }
10366
10367 popup_zqdialog_end();
10368 return ret;
10369 }
10370 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10371 {
10372 if(_selected_tile > -1)
10373 {
10374 tile = _selected_tile;
10375 cs = _selected_tcset;
10376 }
10377 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10378 if(_selected_tile < 0)
10379 {
10380 _selected_tile = tile;
10381 _selected_tcset = cs;
10382 }
10383 return ret;
10384 }
10385
10386 int32_t onTiles()
10387 {
10388 return onGotoTiles(-1);
10389 }
10390
10391 int32_t onGotoTiles(int32_t startfrom)
10392 {
10393 static int32_t t = 0;
10394 if (startfrom > -1)
10395 t = startfrom;
10396 int32_t f = 0;
10397 int32_t c = CSet;
10398 reset_pal_cycling();
10399 // loadlvlpal(Map.CurrScr()->color);
10400 rebuild_trans_table();
10401 select_tile(t, f, 0, c, true);
10402 refresh(rALL);
10403 return D_O_K;
10404 }
10405
10406 int32_t combopage_animate = 1;
10407 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10408 {
10409 if(unsigned(c)<MAXCOMBOS)
10410 {
10411 newcombo& cmb = combobuf[c];
10412 int t = cmb.tile;
10413 if(!animate)
10414 cmb.tile = cmb.o_tile;
10415 put_combo(dest,x,y,c,cs,0,0);
10416 cmb.tile = t;
10417 }
10418 else
10419 {
10420 rectfill(dest,x,y,x+32-1,y+32-1,0);
10421 }
10422 }
10423
10424 void draw_combos(int32_t page,int32_t cs,bool cols)
10425 {
10426 clear_bitmap(screen2);
10427 BITMAP *buf = create_bitmap_ex(8,16,16);
10428
10429 int32_t w = 32;
10430 int32_t h = 32;
10431 int32_t mul = 2;
10432
10433 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10434 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10435 int32_t screen_xofs=window_xofs+6;
10436 int32_t screen_yofs=window_yofs+25;
10437
10438 if(cols==false)
10439 {
10440 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10441 {
10442 int32_t x = (i%COMBOS_PER_ROW)*w;
10443 int32_t y = (i/COMBOS_PER_ROW)*h;
10444
10445 combotile_override_x = x+screen_xofs+(w-16)/2;
10446 combotile_override_y = y+screen_yofs+(h-16)/2;
10447 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10448 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10449 }
10450 }
10451 else
10452 {
10453 int32_t c = 0;
10454
10455 for(int32_t i=0; i<256; i++)
10456 {
10457 int32_t x = (i%COMBOS_PER_ROW)*w;
10458 int32_t y = (i/COMBOS_PER_ROW)*h;
10459
10460 combotile_override_x = x+screen_xofs+(w-16)/2;
10461 combotile_override_y = y+screen_yofs+(h-16)/2;
10462 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10463 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10464 ++c;
10465
10466 if((i&3)==3)
10467 c+=48;
10468
10469 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10470 c-=256;
10471 }
10472 }
10473 combotile_override_x = combotile_override_y = -1;
10474
10475 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10476 {
10477 vline(screen2,x,0,(208*mul)-1,vc(15));
10478 }
10479
10480 destroy_bitmap(buf);
10481 }
10482
10483 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10484 {
10485 int32_t yofs=3;
10486 static BITMAP *buf = create_bitmap_ex(8,16,16);
10487 int32_t mul = 2;
10488 FONT *tfont = get_zc_font(font_lfont_l);
10489
10490 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10491 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10492 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10493
10494 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10495
10496 if(copy>=0)
10497 {
10498 put_combo(buf,0,0,copy,cs,0,0);
10499 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10500
10501 if(copycnt>1)
10502 {
10503 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10504 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10505 }
10506 else
10507 {
10508 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10509 }
10510 }
10511 else
10512 {
10513 if (InvalidBG == 2)
10514 {
10515 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10516 }
10517 else if(InvalidBG == 1)
10518 {
10519 for(int32_t dy=0; dy<16*mul; dy++)
10520 {
10521 for(int32_t dx=0; dx<16*mul; dx++)
10522 {
10523 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10524 }
10525 }
10526 }
10527 else
10528 {
10529 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10530 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10531 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10532 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10533 }
10534 }
10535
10536 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10537 put_combo(buf,0,0,tile,cs,0,0);
10538 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10539
10540 if(tile>tile2)
10541 {
10542 zc_swap(tile,tile2);
10543 }
10544
10545 char cbuf[8];
10546 cbuf[0]=0;
10547
10548 if(tile2!=tile)
10549 {
10550 sprintf(cbuf,"-%d",tile2);
10551 }
10552
10553 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10554 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10555
10556 if(tile2==tile)
10557 {
10558 int32_t nextcombo=combobuf[tile].nextcombo;
10559 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10560 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10561
10562 if(nextcombo>0)
10563 {
10564 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10565 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10566 }
10567 else
10568 {
10569 if (InvalidBG == 2)
10570 {
10571 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10572 }
10573 else if(InvalidBG == 1)
10574 {
10575 for(int32_t dy=0; dy<16*mul; dy++)
10576 {
10577 for(int32_t dx=0; dx<16*mul; dx++)
10578 {
10579 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10580 }
10581 }
10582 }
10583 else
10584 {
10585 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10586 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10587 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10588 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10589 }
10590 }
10591
10592 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10593 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10594 }
10595
10596
10597 FONT *tf = font;
10598 font = tfont;
10599
10600 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10601 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10602
10603 if(buttons&2)
10604 {
10605 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10606 }
10607
10608 if(buttons&4)
10609 {
10610 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10611 }
10612
10613 font = tf;
10614
10615 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10616 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10617 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10618 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10619
10620 int32_t w = 640;
10621 int32_t h = 480;
10622 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10623 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10624 int32_t screen_xofs=window_xofs+6;
10625 int32_t screen_yofs=window_yofs+25;
10626
10627 custom_vsync();
10628 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10629 SCRFIX();
10630 //destroy_bitmap(buf);
10631 }
10632
10633 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10634 {
10635 int32_t page = tile&0xFF00;
10636 tile &= 0xFF;
10637
10638 if(!cols)
10639 tile += s;
10640 else
10641 {
10642 if(s==-COMBOS_PER_ROW)
10643 tile-=4;
10644
10645 if(s==COMBOS_PER_ROW)
10646 tile+=4;
10647
10648 if(s==-1)
10649 tile-=1;
10650
10651 if(s==1)
10652 tile+=1;
10653 }
10654
10655 /*
10656 if(s==1)
10657 {
10658 if((tile&3)==3)
10659 tile+=48;
10660 else
10661 ++tile;
10662 }
10663 if(s==-1)
10664 {
10665 if((tile&3)==0)
10666 tile-=48;
10667 else
10668 --tile;
10669 }
10670 }
10671 */
10672 bound(tile,0,255);
10673 tile += page;
10674
10675 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10676 tile2 = tile;
10677 }
10678
10679 void draw_combo_list_window()
10680 {
10681 int32_t window_xofs=0;
10682 int32_t window_yofs=0;
10683 int32_t w = 640;
10684 int32_t h = 480;
10685
10686 window_xofs=(zq_screen_w-w-12)>>1;
10687 window_yofs=(zq_screen_h-h-25-6)>>1;
10688 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10689 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10690 FONT *oldfont = font;
10691 font = get_zc_font(font_lfont);
10692 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10693 font=oldfont;
10694 }
10695
10696
10697 static int32_t _selected_combo=-1, _selected_cset=-1;
10698 bool select_combo_2(int32_t &cmb,int32_t &cs)
10699 {
10700 popup_zqdialog_start();
10701 reset_combo_animations();
10702 reset_combo_animations2();
10703 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10704 // static int32_t cmb=0;
10705 int32_t page=cmb>>8;
10706 int32_t tile2=cmb;
10707 int32_t done=0;
10708 int32_t tile_clicked=-1;
10709 int32_t t2;
10710 int32_t copy=-1;
10711 int32_t copycnt=0;
10712
10713 position_mouse_z(0);
10714
10715 go();
10716 int32_t w = 640;
10717 int32_t h = 480;
10718 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10719 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10720 int32_t screen_xofs=window_xofs+6;
10721 int32_t screen_yofs=window_yofs+25;
10722 int32_t panel_yofs=3;
10723 int32_t mul = 2;
10724 FONT *tfont = get_zc_font(font_lfont_l);
10725
10726 draw_combo_list_window();
10727 draw_combos(page,cs,combo_cols);
10728 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10729
10730 while(gui_mouse_b())
10731 {
10732 /* do nothing */
10733 rest(1);
10734 }
10735
10736 bool bdown=false;
10737 int32_t f=0;
10738 int otl = cmb, otl2 = tile2;
10739
10740 do
10741 {
10742 HANDLE_CLOSE_ZQDLG();
10743 if(exiting_program) break;
10744 rest(4);
10745 bool redraw=false;
10746
10747 if(mouse_z<0)
10748 {
10749 if(page<COMBO_PAGES-1)
10750 {
10751 ++page;
10752 cmb=tile2=(page<<8)+(cmb&0xFF);
10753 }
10754
10755 position_mouse_z(0);
10756 redraw=true;
10757 }
10758 else if(mouse_z>0)
10759 {
10760 if(page>0)
10761 {
10762 --page;
10763 cmb=tile2=(page<<8)+(cmb&0xFF);
10764 }
10765
10766 position_mouse_z(0);
10767 redraw=true;
10768 }
10769
10770 if(keypressed())
10771 {
10772 switch(readkey()>>8)
10773 {
10774 case KEY_DEL:
10775 cmb=0;
10776 done=2;
10777 break;
10778
10779 case KEY_ENTER_PAD:
10780 case KEY_ENTER:
10781 done=2;
10782 break;
10783
10784 case KEY_ESC:
10785 done=1;
10786 break;
10787
10788 case KEY_F1:
10789 onHelp();
10790 break;
10791
10792 case KEY_SPACE:
10793 combo_cols=!combo_cols;
10794 redraw=true;
10795 break;
10796
10797 case KEY_EQUALS:
10798 case KEY_PLUS_PAD:
10799 cs = (cs<13) ? cs+1:0;
10800 redraw=true;
10801 break;
10802
10803 case KEY_MINUS:
10804 case KEY_MINUS_PAD:
10805 cs = (cs>0) ? cs-1:13;
10806 redraw=true;
10807 break;
10808
10809 case KEY_UP:
10810 sel_combo(cmb,tile2,-COMBOS_PER_ROW,combo_cols);
10811 redraw=true;
10812 break;
10813
10814 case KEY_DOWN:
10815 sel_combo(cmb,tile2,COMBOS_PER_ROW,combo_cols);
10816 redraw=true;
10817 break;
10818
10819 case KEY_LEFT:
10820 sel_combo(cmb,tile2,-1,combo_cols);
10821 redraw=true;
10822 break;
10823
10824 case KEY_RIGHT:
10825 sel_combo(cmb,tile2,1,combo_cols);
10826 redraw=true;
10827 break;
10828
10829 case KEY_PGUP:
10830 if(page>0)
10831 {
10832 --page;
10833 cmb=tile2=(page<<8)+(cmb&0xFF);
10834 }
10835
10836 redraw=true;
10837 break;
10838
10839 case KEY_PGDN:
10840 if(page<COMBO_PAGES-1)
10841 {
10842 ++page;
10843 cmb=tile2=(page<<8)+(cmb&0xFF);
10844 }
10845
10846 redraw=true;
10847 break;
10848
10849 case KEY_P:
10850 {
10851 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10852
10853 if(!cancelgetnum)
10854 page=(zc_min(choosepage,COMBO_PAGES-1));
10855
10856 cmb=tile2=(page<<8)+(cmb&0xFF);
10857 redraw=true;
10858 break;
10859 }
10860 }
10861
10862 clear_keybuf();
10863 }
10864
10865 if(gui_mouse_b()&1)
10866 {
10867 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10868 {
10869 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10870 {
10871 done=1;
10872 }
10873 }
10874
10875 int32_t x=gui_mouse_x()-screen_xofs;
10876 int32_t y=gui_mouse_y()-screen_yofs;
10877
10878 if(y>=0 && y<208*mul)
10879 {
10880 x=zc_min(zc_max(x,0),(320*mul)-1);
10881 int32_t t;
10882
10883 if(!combo_cols)
10884 {
10885 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10886 }
10887 else
10888 {
10889 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10890 }
10891
10892 bound(t,0,255);
10893 t+=page<<8;
10894 cmb=tile2=t;
10895
10896 if(tile_clicked!=t)
10897 {
10898 dclick_status=DCLICK_NOT;
10899 }
10900 else if(dclick_status == DCLICK_AGAIN)
10901 {
10902 while(gui_mouse_b())
10903 {
10904 /* do nothing */
10905 }
10906
10907 if(!combo_cols)
10908 {
10909 t2 = (y>>5)*COMBOS_PER_ROW + (x>>5);
10910 }
10911 else
10912 {
10913 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10914 }
10915
10916 if(t2!=t)
10917 {
10918 dclick_status=DCLICK_NOT;
10919 }
10920 else
10921 {
10922 done=2;
10923 }
10924 }
10925
10926 tile_clicked=t;
10927 }
10928 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10929 {
10930 if(y<(224*mul)+panel_yofs && page>0)
10931 {
10932 --page;
10933 redraw=true;
10934 }
10935
10936 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
10937 {
10938 ++page;
10939 redraw=true;
10940 }
10941
10942 bdown=true;
10943 }
10944
10945 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
10946 {
10947 FONT *tf = font;
10948 font = tfont;
10949
10950 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
10951 {
10952 done=2;
10953 }
10954
10955 font = tf;
10956 }
10957 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
10958 {
10959 FONT *tf = font;
10960 font = tfont;
10961
10962 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
10963 combopage_animate = combopage_animate ? 0 : 1;
10964 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
10965 redraw = true;
10966
10967 font = tf;
10968 }
10969
10970 bdown=true;
10971 }
10972
10973 bool r_click = false;
10974
10975 if(gui_mouse_b()&2 && !bdown)
10976 {
10977 int32_t x=gui_mouse_x()+screen_xofs;
10978 int32_t y=gui_mouse_y()+screen_yofs;
10979
10980 if(y>=0 && y<208*mul)
10981 {
10982 x=zc_min(zc_max(x,0),(320*mul)-1);
10983 int32_t t;
10984
10985 if(!combo_cols)
10986 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10987 else
10988 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10989
10990 bound(t,0,255);
10991 t+=page<<8;
10992
10993 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
10994 cmb=tile2=t;
10995 }
10996
10997 bdown = r_click = true;
10998 f=8;
10999 }
11000
11001 if(gui_mouse_b()==0)
11002 bdown=false;
11003
11004 if((f%8) || InvalidBG == 1)
11005 redraw = true;
11006 if(otl != cmb || otl2 != tile2)
11007 {
11008 otl = cmb;
11009 otl2 = tile2;
11010 redraw = true;
11011 }
11012
11013 if(redraw || combopage_animate)
11014 draw_combos(page,cs,combo_cols);
11015
11016 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11017
11018 if(f&8)
11019 {
11020 int32_t x,y;
11021
11022 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11023 {
11024 if((i>>8)==page)
11025 {
11026 int32_t t=i&255;
11027
11028 if(!combo_cols)
11029 {
11030 x=(t%COMBOS_PER_ROW)<<5;
11031 y=(t/COMBOS_PER_ROW)<<5;
11032 }
11033 else
11034 {
11035 x=((t&3) + ((t/52)<<2)) << 5;
11036 y=((t%52)>>2) << 5;
11037 }
11038
11039 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11040 }
11041 }
11042
11043 SCRFIX();
11044 }
11045
11046 ++f;
11047
11048 }
11049 while(!done);
11050
11051 while(gui_mouse_b())
11052 {
11053 /* do nothing */
11054 rest(1);
11055 }
11056
11057 comeback();
11058 setup_combo_animations();
11059 setup_combo_animations2();
11060
11061 bool ret = done==2;
11062 if(ret)
11063 {
11064 _selected_combo = cmb;
11065 _selected_cset = cs;
11066 }
11067
11068 popup_zqdialog_end();
11069 return ret;
11070 }
11071
11072 bool select_combo_3(int32_t &cmb,int32_t &cs)
11073 {
11074 if(_selected_combo < 0)
11075 {
11076 _selected_combo = Combo;
11077 _selected_cset = CSet;
11078 }
11079 cmb = _selected_combo;
11080 cs = _selected_cset;
11081 return select_combo_2(cmb,cs);
11082 }
11083
11084 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11085 {
11086 static bitstring pasteflags;
11087 static const vector<CheckListInfo> advp_names =
11088 {
11089 { "Tile" },
11090 { "CSet2" },
11091 { "Solidity" },
11092 { "Animation" },
11093 { "Type" },
11094 { "Inherent Flag" },
11095 { "Attribytes" },
11096 { "Attrishorts" },
11097 { "Attributes" },
11098 { "Flags", "The 16 Flags on the 'Flags' tab" },
11099 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11100 { "Label" },
11101 { "Script" },
11102 { "Effect" },
11103 { "Triggers Tab" },
11104 { "Lifting Tab" },
11105 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11106 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11107 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11108 };
11109 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11110 return false;
11111
11112 //Paste to each combo in the range
11113 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11114 {
11115 combobuf[i].advpaste(combobuf[copy], pasteflags);
11116 }
11117
11118 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11119 {
11120 setup_combo_animations();
11121 setup_combo_animations2();
11122 }
11123
11124 return true;
11125 }
11126
11127 int32_t combo_screen(int32_t pg, int32_t tl)
11128 {
11129 popup_zqdialog_start();
11130 reset_combo_animations();
11131 reset_combo_animations2();
11132 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11133 static int32_t tile=0;
11134 static int32_t page=0;
11135
11136 if(pg>-1)
11137 page = pg;
11138
11139 if(tl>-1)
11140 tile = tl;
11141
11142 int32_t tile2=tile;
11143 int32_t done=0;
11144 int32_t cs = CSet;
11145 int32_t copy=-1;
11146 int32_t copycnt=0;
11147
11148 int32_t tile_clicked=-1;
11149 int32_t t2;
11150
11151 bool masscopy;
11152
11153 go();
11154 int32_t w = 640;
11155 int32_t h = 480;
11156 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11157 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11158 int32_t screen_xofs=window_xofs+6;
11159 int32_t screen_yofs=window_yofs+25;
11160 int32_t panel_yofs=3;
11161 int32_t mul = 2;
11162 FONT *tfont = get_zc_font(font_lfont_l);
11163
11164 draw_combo_list_window();
11165 draw_combos(page,cs,combo_cols);
11166 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11167 go_combos();
11168 position_mouse_z(0);
11169
11170 while(gui_mouse_b())
11171 {
11172 /* do nothing */
11173 }
11174
11175 bool bdown=false;
11176 int32_t f=0;
11177 int otl = tile, otl2 = tile2;
11178
11179 do
11180 {
11181 HANDLE_CLOSE_ZQDLG();
11182 if(exiting_program) break;
11183 rest(4);
11184 bool redraw=false;
11185
11186 if(mouse_z<0)
11187 {
11188 if(page<COMBO_PAGES-1)
11189 {
11190 ++page;
11191 tile=tile2=(page<<8)+(tile&0xFF);
11192 }
11193
11194 position_mouse_z(0);
11195 redraw=true;
11196 }
11197 else if(mouse_z>0)
11198 {
11199 if(page>0)
11200 {
11201 --page;
11202 tile=tile2=(page<<8)+(tile&0xFF);
11203 }
11204
11205 position_mouse_z(0);
11206 redraw=true;
11207 }
11208
11209 if(keypressed())
11210 {
11211 switch(readkey()>>8)
11212 {
11213 case KEY_ENTER_PAD:
11214 case KEY_ENTER:
11215 done=2;
11216 break;
11217
11218 case KEY_ESC:
11219 done=1;
11220 break;
11221
11222 case KEY_F1:
11223 onHelp();
11224 break;
11225
11226 case KEY_SPACE:
11227 combo_cols=!combo_cols;
11228 redraw=true;
11229 break;
11230
11231 case KEY_EQUALS:
11232 case KEY_PLUS_PAD:
11233 if(CHECK_CTRL_CMD)
11234 {
11235 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11236 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11237 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11238
11239 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11240 {
11241 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11242 0, NEWMAXTILES-1));
11243 }
11244
11245 setup_combo_animations();
11246 redraw=true;
11247 }
11248 else
11249 {
11250 cs = (cs<13) ? cs+1:0;
11251 redraw=true;
11252 }
11253
11254 break;
11255
11256 case KEY_MINUS:
11257 case KEY_MINUS_PAD:
11258 if(CHECK_CTRL_CMD)
11259 {
11260 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11261 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11262 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11263
11264 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11265 {
11266 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11267 0, NEWMAXTILES-1));
11268 }
11269
11270 setup_combo_animations();
11271 redraw=true;
11272 }
11273 else
11274 {
11275 cs = (cs>0) ? cs-1:13;
11276 redraw=true;
11277 }
11278
11279 break;
11280
11281 case KEY_UP:
11282 sel_combo(tile,tile2,-COMBOS_PER_ROW,combo_cols);
11283 redraw=true;
11284 break;
11285
11286 case KEY_DOWN:
11287 sel_combo(tile,tile2,COMBOS_PER_ROW,combo_cols);
11288 redraw=true;
11289 break;
11290
11291 case KEY_LEFT:
11292 sel_combo(tile,tile2,-1,combo_cols);
11293 redraw=true;
11294 break;
11295
11296 case KEY_RIGHT:
11297 sel_combo(tile,tile2,1,combo_cols);
11298 redraw=true;
11299 break;
11300
11301 case KEY_PGUP:
11302 if(page>0)
11303 {
11304 --page;
11305 tile=tile2=(page<<8)+(tile&0xFF);
11306 }
11307
11308 redraw=true;
11309 break;
11310
11311 case KEY_PGDN:
11312 if(page<COMBO_PAGES-1)
11313 {
11314 ++page;
11315 tile=tile2=(page<<8)+(tile&0xFF);
11316 }
11317
11318 redraw=true;
11319 break;
11320
11321 case KEY_A:
11322 {
11323 tile=(page<<8);
11324 tile2=(page<<8)+(0xFF);
11325 }
11326
11327 redraw=true;
11328 break;
11329
11330 case KEY_P:
11331 {
11332 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11333
11334 if(!cancelgetnum)
11335 page=(zc_min(choosepage,COMBO_PAGES-1));
11336
11337 tile=tile2=(page<<8)+(tile&0xFF);
11338 redraw=true;
11339 }
11340 break;
11341
11342 case KEY_U:
11343 comeback_combos();
11344 redraw=true;
11345 break;
11346
11347 case KEY_E:
11348 go_combos();
11349 edit_combo(tile,false,cs);
11350 redraw=true;
11351 setup_combo_animations();
11352 setup_combo_animations2();
11353 break;
11354
11355 case KEY_C:
11356 go_combos();
11357 copy=zc_min(tile,tile2);
11358 copycnt=abs(tile-tile2)+1;
11359 redraw=true;
11360 break;
11361
11362 case KEY_H:
11363 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11364 {
11365 combobuf[i].flip^=1;
11366 byte w2=combobuf[i].walk;
11367 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11368 w2=combobuf[i].csets;
11369 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11370 }
11371
11372 redraw=true;
11373 saved=false;
11374 break;
11375
11376 case KEY_M:
11377 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11378 {
11379 move_combos(tile,tile2,copy,copycnt);
11380 saved=false;
11381 }
11382
11383 redraw=true;
11384 break;
11385
11386 case KEY_S:
11387 tile=tile2=zc_min(tile,tile2);
11388
11389 if(copy>=0 && tile!=copy)
11390 {
11391 go_combos();
11392
11393 for(int32_t i=0; i<copycnt; i++)
11394 {
11395 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11396 }
11397
11398 saved=false;
11399 setup_combo_animations();
11400 setup_combo_animations2();
11401 }
11402
11403 redraw=true;
11404 copy=-1;
11405 break;
11406
11407 case KEY_V:
11408 if((CHECK_CTRL_CMD) && copy != -1)
11409 {
11410 if(advpaste(tile, tile2, copy))
11411 {
11412 saved=false;
11413 redraw=true;
11414 copy=-1;
11415 }
11416
11417 break;
11418 }
11419
11420 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11421
11422 if(copy==-1)
11423 {
11424 go_combos();
11425
11426 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11427 {
11428 combobuf[i].flip^=2;
11429 byte w2=combobuf[i].walk;
11430 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11431 w2=combobuf[i].csets;
11432 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11433 }
11434
11435 saved=false;
11436 }
11437 else
11438 {
11439 go_combos();
11440 copy_combos(tile,tile2,copy,copycnt,masscopy);
11441 setup_combo_animations();
11442 setup_combo_animations2();
11443 saved=false;
11444 }
11445
11446 redraw=true;
11447 break;
11448 case KEY_R:
11449 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11450 {
11451 combobuf[i].flip = rotate_value(combobuf[i].flip);
11452 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11453 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11454 }
11455
11456 redraw=true;
11457 saved=false;
11458 break;
11459
11460 case KEY_I:
11461 {
11462 // rev.1509; Can now insert/remove all selected combos
11463 int32_t z=tile;
11464 int32_t numSelected = abs(tile-tile2) + 1;
11465 tile=zc_min(tile,tile2);
11466 tile2=MAXCOMBOS;
11467 copy = tile + numSelected; // copy=tile+1;
11468 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11469
11470 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11471 {
11472 char buf[64];
11473
11474 if(numSelected>1)
11475 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11476 else
11477 sprintf(buf,"Remove combo %d?",tile);
11478
11479 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11480 {
11481 move_combos(tile,tile2,copy, copycnt);
11482 //don't allow the user to undo; quest combo references are incorrect -DD
11483 go_combos();
11484 redraw=true;
11485 saved=false;
11486 }
11487 }
11488 else
11489 {
11490 char buf[64];
11491
11492 if(numSelected>1)
11493 sprintf(buf,"Insert %d blank combos?",numSelected);
11494 else
11495 sprintf(buf,"Insert a blank combo?");
11496
11497 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11498 {
11499 move_combos(copy,tile2,tile, copycnt);
11500 go_combos();
11501 redraw=true;
11502 saved=false;
11503 }
11504 }
11505
11506 copy=-1;
11507 tile2=tile=z;
11508 }
11509 break;
11510
11511 case KEY_DEL:
11512 {
11513 char buf[40];
11514
11515 if(tile==tile2)
11516 {
11517 sprintf(buf,"Delete combo %d?",tile);
11518 }
11519 else
11520 {
11521 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11522 }
11523
11524 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11525 {
11526 go_combos();
11527
11528 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11529 {
11530 clear_combo(i);
11531 }
11532
11533 tile=tile2=zc_min(tile,tile2);
11534 redraw=true;
11535 saved=false;
11536 setup_combo_animations();
11537 setup_combo_animations2();
11538 }
11539 }
11540 break;
11541 }
11542
11543 clear_keybuf();
11544 }
11545
11546 if(gui_mouse_b()&1)
11547 {
11548 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11549 {
11550 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11551 {
11552 done=1;
11553 }
11554 }
11555
11556 int32_t x=gui_mouse_x()-screen_xofs;
11557 int32_t y=gui_mouse_y()-screen_yofs;
11558
11559 if(y>=0 && y<(208*mul))
11560 {
11561 x=zc_min(zc_max(x,0),(320*mul)-1);
11562 int32_t t;
11563
11564 if(!combo_cols)
11565 {
11566 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11567 }
11568 else
11569 {
11570 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11571 }
11572
11573 bound(t,0,255);
11574 t+=page<<8;
11575
11576 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11577 {
11578 tile2=t;
11579 }
11580 else
11581 {
11582 tile=tile2=t;
11583 }
11584
11585 if(tile_clicked!=t)
11586 {
11587 dclick_status=DCLICK_NOT;
11588 }
11589 else if(dclick_status == DCLICK_AGAIN)
11590 {
11591 while(gui_mouse_b())
11592 {
11593 /* do nothing */
11594 rest(1);
11595 }
11596
11597 if(!combo_cols)
11598 {
11599 t2 = (y>>4)*COMBOS_PER_ROW + (x>>4);
11600 }
11601 else
11602 {
11603 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11604 }
11605
11606 bound(t2,0,255);
11607 t2+=page<<8;
11608
11609 if(t2!=t)
11610 {
11611 dclick_status=DCLICK_NOT;
11612 }
11613 else
11614 {
11615 go_combos();
11616 edit_combo(tile,false,cs);
11617 redraw=true;
11618 setup_combo_animations();
11619 setup_combo_animations2();
11620 }
11621 }
11622
11623 tile_clicked=t;
11624 }
11625 else if(x>(300*mul) && !bdown)
11626 {
11627 if(y<(224*mul)+panel_yofs && page>0)
11628 {
11629 --page;
11630 redraw=true;
11631 }
11632
11633 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11634 {
11635 ++page;
11636 redraw=true;
11637 }
11638
11639 bdown=true;
11640 }
11641
11642 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11643 {
11644 FONT *tf = font;
11645 font = tfont;
11646
11647 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11648 {
11649 font = tf;
11650 edit_combo(tile,false,cs);
11651 redraw=true;
11652 }
11653
11654 font = tf;
11655 }
11656 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11657 {
11658 FONT *tf = font;
11659 font = tfont;
11660
11661 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11662 {
11663 done=1;
11664 }
11665
11666 font = tf;
11667 }
11668 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11669 {
11670 FONT *tf = font;
11671 font = tfont;
11672
11673 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11674 combopage_animate = combopage_animate ? 0 : 1;
11675 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11676 redraw = true;
11677
11678 font = tf;
11679 }
11680
11681 bdown=true;
11682 }
11683
11684 bool r_click = false;
11685
11686 if(gui_mouse_b()&2 && !bdown)
11687 {
11688 int32_t x=gui_mouse_x()-screen_xofs;
11689 int32_t y=gui_mouse_y()-screen_yofs;
11690
11691 if(y>=0 && y<(208*mul))
11692 {
11693 x=zc_min(zc_max(x,0),(320*mul)-1);
11694 int32_t t;
11695
11696 if(!combo_cols)
11697 {
11698 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11699 }
11700 else
11701 {
11702 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11703 }
11704
11705 bound(t,0,255);
11706 t+=page<<8;
11707
11708 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11709 {
11710 tile=tile2=t;
11711 }
11712 }
11713
11714 bdown = r_click = true;
11715 f=8;
11716 }
11717
11718 REDRAW:
11719
11720 if(gui_mouse_b()==0)
11721 bdown=false;
11722
11723 if((f%8) || InvalidBG == 1)
11724 redraw = true;
11725 if(otl != tile || otl2 != tile2)
11726 {
11727 otl = tile;
11728 otl2 = tile2;
11729 redraw = true;
11730 }
11731
11732 if(redraw || combopage_animate)
11733 draw_combos(page,cs,combo_cols);
11734
11735 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11736
11737 if(f&8)
11738 {
11739 int32_t x,y;
11740
11741 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11742 {
11743 if((i>>8)==page)
11744 {
11745 int32_t t=i&255;
11746
11747 if(!combo_cols)
11748 {
11749 x=(t%COMBOS_PER_ROW)<<5;
11750 y=(t/COMBOS_PER_ROW)<<5;
11751 }
11752 else
11753 {
11754 x=((t&3) + ((t/52)<<2)) << 5;
11755 y=((t%52)>>2) << 5;
11756 }
11757
11758 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11759 }
11760 }
11761
11762 SCRFIX();
11763 }
11764
11765 ++f;
11766
11767 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11768 if(r_click)
11769 {
11770 NewMenu rcmenu
11771 {
11772 { "Copy", [&]()
11773 {
11774 go_combos();
11775 copy=zc_min(tile,tile2);
11776 copycnt=abs(tile-tile2)+1;
11777 } },
11778 { "Paste", [&]()
11779 {
11780 if((CHECK_CTRL_CMD) && copy != -1)
11781 {
11782 if(advpaste(tile, tile2, copy))
11783 {
11784 saved=false;
11785 redraw=true;
11786 copy=-1;
11787 }
11788 return;
11789 }
11790
11791 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11792
11793 if(copy>-1)
11794 {
11795 go_combos();
11796 copy_combos(tile,tile2,copy,copycnt,masscopy);
11797 setup_combo_animations();
11798 setup_combo_animations2();
11799 saved=false;
11800 }
11801 } },
11802 { "Adv. Paste", [&]()
11803 {
11804 if(copy > -1)
11805 {
11806 if(advpaste(tile, tile2, copy))
11807 {
11808 saved=false;
11809 redraw=true;
11810 copy=-1;
11811 }
11812 }
11813 } },
11814 { "Swap", [&]()
11815 {
11816 tile=tile2=zc_min(tile,tile2);
11817
11818 if(copy>=0 && tile!=copy)
11819 {
11820 go_combos();
11821
11822 for(int32_t i=0; i<copycnt; i++)
11823 {
11824 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11825 }
11826
11827 saved=false;
11828 setup_combo_animations();
11829 setup_combo_animations2();
11830 }
11831 copy=-1;
11832 } },
11833 { "Delete", [&]()
11834 {
11835 string msg;
11836
11837 if(tile==tile2)
11838 msg = fmt::format("Delete combo {}?",tile);
11839 else
11840 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11841 bool didconfirm = false;
11842 AlertDialog("Confirm Delete",msg,
11843 [&](bool ret,bool)
11844 {
11845 if(ret)
11846 didconfirm = true;
11847 }).show();
11848 if(didconfirm)
11849 {
11850 go_combos();
11851
11852 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11853 clear_combo(i);
11854
11855 tile=tile2=zc_min(tile,tile2);
11856 saved=false;
11857 }
11858 } },
11859 {},
11860 { "Edit", [&]()
11861 {
11862 go_combos();
11863 edit_combo(tile,false,cs);
11864 } },
11865 { "Insert", [&]()
11866 {
11867 int z = tile;
11868 int count = abs(tile-tile2)+1;
11869 tile = zc_min(tile,tile2);
11870 tile2 = MAXCOMBOS;
11871 copy = tile+count;
11872 copycnt = MAXCOMBOS-tile-count;
11873
11874 string msg;
11875
11876 if(count>1)
11877 msg = fmt::format("Insert combos {} - {}?"
11878 " This will offset all of the combos that follow!",tile, copy-1);
11879 else
11880 msg = fmt::format("Insert combo {}?"
11881 " This will offset all of the combos that follow!",tile);
11882
11883 bool didconfirm = false;
11884 AlertDialog("Confirm Insert",msg,
11885 [&](bool ret,bool)
11886 {
11887 if(ret)
11888 didconfirm = true;
11889 }).show();
11890 if(didconfirm)
11891 move_combos(copy, tile2, tile, copycnt);
11892 else return;
11893
11894 copy = -1;
11895 tile2 = tile = z;
11896
11897 //don't allow the user to undo; quest combo references are incorrect -DD
11898 go_combos();
11899 saved = false;
11900 } },
11901 { "Remove", [&]()
11902 {
11903 int z = tile;
11904 int count = abs(tile-tile2)+1;
11905 tile = zc_min(tile,tile2);
11906 tile2 = MAXCOMBOS;
11907 copy = tile+count;
11908 copycnt = MAXCOMBOS-tile-count;
11909
11910 string msg;
11911
11912 if(count>1)
11913 msg = fmt::format("Remove combos {} - {}?"
11914 " This will offset all of the combos that follow!",tile, copy-1);
11915 else
11916 msg = fmt::format("Remove combo {}?"
11917 " This will offset all of the combos that follow!",tile);
11918
11919 bool didconfirm = false;
11920 AlertDialog("Confirm Remove",msg,
11921 [&](bool ret,bool)
11922 {
11923 if(ret)
11924 didconfirm = true;
11925 }).show();
11926 if(didconfirm)
11927 move_combos(tile, tile2, copy, copycnt);
11928 else return;
11929
11930 copy = -1;
11931 tile2 = tile = z;
11932
11933 //don't allow the user to undo; quest combo references are incorrect -DD
11934 go_combos();
11935 saved = false;
11936 } },
11937 {},
11938 { "Locations", [&]()
11939 {
11940 int32_t z = Combo;
11941 Combo = tile;
11942 onComboLocationReport();
11943 Combo = z;
11944 } },
11945 };
11946 rcmenu.pop(window_mouse_x(),window_mouse_y());
11947 redraw = true;
11948 r_click = false;
11949 goto REDRAW;
11950 }
11951
11952 }
11953 while(!done);
11954
11955 while(gui_mouse_b())
11956 rest(1);
11957 comeback();
11958 setup_combo_animations();
11959 setup_combo_animations2();
11960 _selected_combo = tile;
11961 _selected_cset = cs;
11962 popup_zqdialog_end();
11963 return done-1;
11964 }
11965
11966 int32_t onCombos()
11967 {
11968 // reset_combo_animations();
11969 combo_screen(-1,-1);
11970 // setup_combo_animations();
11971 refresh(rALL);
11972 return D_O_K;
11973 }
11974
11975 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11976 {
11977 //these are here to bypass compiler warnings about unused arguments
11978 d=d;
11979 c=c;
11980
11981 if(msg==MSG_CLICK)
11982 {
11983 int32_t t=curr_combo.o_tile;
11984 int32_t f=curr_combo.flip;
11985
11986 if(select_tile(t,f,1,CSet,true,0,true))
11987 {
11988 curr_combo.tile=t;
11989 curr_combo.o_tile=t;
11990 curr_combo.flip=f;
11991 return D_REDRAW;
11992 }
11993 }
11994
11995 return D_O_K;
11996 }
11997
11998 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
11999 {
12000 //these are here to bypass compiler warnings about unused arguments
12001 c=c;
12002
12003 if(msg==MSG_DRAW)
12004 {
12005 FONT *f = get_zc_font(font_lfont_l);
12006 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12007 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12008 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12009 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12010 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12011 }
12012
12013 return D_O_K;
12014 }
12015
12016 int32_t click_d_ctile_proc()
12017 {
12018 d_ctile_proc(MSG_CLICK,NULL,0);
12019 return D_REDRAW;
12020 }
12021
12022 int32_t click_d_combo_proc();
12023
12024 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12025 {
12026 if(index<0)
12027 {
12028 *list_size = bidcomboscripts_cnt;
12029 return NULL;
12030 }
12031
12032 return bidcomboscripts[index].first.c_str();
12033 }
12034 9 ListData comboscript_list(comboscriptdroplist, &font);
12035
12036 bool call_combo_editor(int32_t);
12037 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12038 {
12039 FONT* ofont = font;
12040 //CSet = cs;
12041 reset_combo_animations();
12042 reset_combo_animations2();
12043 bool edited = call_combo_editor(c);
12044 font = ofont;
12045
12046 if(freshen)
12047 {
12048 refresh(rALL);
12049 }
12050
12051 setup_combo_animations();
12052 setup_combo_animations2();
12053
12054 return edited;
12055 }
12056
12057 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12058 {
12059 switch(msg)
12060 {
12061 case MSG_CLICK:
12062 {
12063 int32_t cs = d->d2;
12064 int32_t f = 0;
12065
12066 if(select_tile(d->d1,f,1,cs,true))
12067 {
12068 int32_t ok=1;
12069
12070 if(newtilebuf[d->d1].format==tf8Bit)
12071 jwin_alert("Warning",
12072 "You have selected an 8-bit tile.",
12073 "It will not be drawn correctly",
12074 "on the file select screen.",
12075 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12076
12077 return D_REDRAW;
12078 }
12079 }
12080 break;
12081
12082 case MSG_DRAW:
12083 d->w = 32+4;
12084 d->h = 32+4;
12085
12086 BITMAP *buf = create_bitmap_ex(8,16,16);
12087 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12088
12089 if(buf && bigbmp)
12090 {
12091 clear_bitmap(buf);
12092 overtile16(buf,d->d1,0,0,d->fg,0);
12093 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12094 destroy_bitmap(buf);
12095 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12096 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12097 destroy_bitmap(bigbmp);
12098 }
12099
12100 break;
12101 }
12102
12103 return D_O_K;
12104 }
12105
12106 static DIALOG icon_dlg[] =
12107 {
12108 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12109 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12110 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12111 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12112 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12113 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12114 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12115 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12116 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12117 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12118 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12119 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12120 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12121 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12122 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12123 };
12124
12125 int32_t onIcons()
12126 {
12127 PALETTE pal;
12128 // pal = RAMpal;
12129 memcpy(pal,RAMpal,sizeof(RAMpal));
12130 icon_dlg[0].dp2=get_zc_font(font_lfont);
12131
12132 for(int32_t i=0; i<4; i++)
12133 {
12134 icon_dlg[i+2].d1 = QMisc.icons[i];
12135 icon_dlg[i+2].fg = i+6;
12136 load_cset(pal, i+6, pSprite(i+spICON1));
12137 }
12138
12139 zc_set_palette(pal);
12140
12141 large_dialog(icon_dlg);
12142
12143 int32_t ret = do_zqdialog(icon_dlg,7);
12144
12145 if(ret==6)
12146 {
12147 for(int32_t i=0; i<4; i++)
12148 {
12149 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12150 {
12151 QMisc.icons[i] = icon_dlg[i+2].d1;
12152 saved=false;
12153 }
12154 }
12155 }
12156
12157 zc_set_palette(RAMpal);
12158 return D_O_K;
12159 }
12160
12161 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12162 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12163 {
12164 if(msg == MSG_DRAW)
12165 {
12166 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12167 }
12168
12169 return D_O_K;
12170 }
12171
12172 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12173 {
12174 switch(msg)
12175 {
12176 case MSG_CLICK:
12177 {
12178 if((d->flags&D_NOCLICK))
12179 break;
12180
12181 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12182 int32_t combo2;
12183 int32_t cs;
12184
12185 if(CHECK_ALT) //place selected cmb/cs
12186 {
12187 if(gui_mouse_b()&1)
12188 {
12189 if(!CHECK_SHIFT)
12190 d->d1 = Combo;
12191 d->fg = CSet;
12192 }
12193
12194 return ret|D_REDRAW;
12195 }
12196 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12197 {
12198 d->d1=0;
12199 d->fg=0;
12200 return ret|D_REDRAW;
12201 }
12202 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12203 {
12204 combo2=d->d1;
12205 cs=d->fg;
12206
12207 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12208 {
12209 d->d1=combo2;
12210 d->fg=cs;
12211 }
12212
12213 return ret|D_REDRAW;
12214 }
12215 else return ret|D_REDRAWME;
12216 }
12217 break;
12218
12219 case MSG_DRAW:
12220 {
12221 d->w = 32;
12222 d->h = 32;
12223
12224 BITMAP *buf = create_bitmap_ex(8,16,16);
12225 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12226
12227 if(buf && bigbmp)
12228 {
12229 clear_bitmap(buf);
12230
12231 if(d->d1==-1) // Display curr_combo instead of combobuf
12232 {
12233 newcombo hold = combobuf[0];
12234 combobuf[0] = curr_combo;
12235 putcombo(buf,0,0,0,d->fg);
12236 combobuf[0] = hold;
12237 }
12238 else if(d->d1)
12239 {
12240 putcombo(buf,0,0,d->d1,d->fg);
12241 }
12242
12243 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12244 destroy_bitmap(buf);
12245 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12246 destroy_bitmap(bigbmp);
12247 }
12248 }
12249 break;
12250 }
12251 return D_O_K;
12252 }
12253
12254 // Hey, let's have a few hundred more lines of code, why not.
12255
12256 #define MR_4BIT 0
12257 #define MR_8BIT 1
12258
12259 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12260 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12261 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12262
12263 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12264 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12265
12266 static int32_t massRecolorDraggedColor=-1;
12267 static int32_t massRecolorCSet;
12268 static bool massRecolorIgnoreBlank=true;
12269 static byte massRecolorType=MR_4BIT;
12270
12271 // Shows the sets of colors to replace from/to.
12272 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12273 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12274 #define D_CSET D_USER
12275 #define D_SETTABLE (D_USER<<1)
12276 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12277 {
12278 BITMAP* bmp=screen;
12279 int32_t colorWidth=(d->w-4)/16;
12280 byte* colors=static_cast<byte*>(d->dp);
12281
12282 switch(msg)
12283 {
12284 case MSG_DRAW:
12285 {
12286 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12287
12288 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12289 for(int32_t c=0; c<16; c++)
12290 {
12291 rectfill(bmp,
12292 d->x+2+c*colorWidth, d->y+2,
12293 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12294 baseColor+colors[c]);
12295 }
12296 }
12297 break;
12298
12299 case MSG_LPRESS:
12300 {
12301 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12302
12303 if(x >= 0 && x < 16) //sanity check!
12304 {
12305 massRecolorDraggedColor=colors[x];
12306 }
12307 }
12308 break;
12309
12310 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12311 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12312 {
12313 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12314 if(x >= 0 && x < 16) //sanity check!
12315 {
12316 colors[x]=massRecolorDraggedColor;
12317 d->flags|=D_DIRTY;
12318 }
12319 }
12320 massRecolorDraggedColor=-1;
12321 break;
12322 }
12323
12324 return D_O_K;
12325 }
12326
12327 // Used for the full palette in 8-bit mode.
12328 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12329 {
12330 BITMAP* bmp=screen;
12331 int colorWidth=(d->w-4)/16;
12332 d->h = 4+(colorWidth*14);
12333 int colorHeight=colorWidth;
12334
12335 switch(msg)
12336 {
12337 case MSG_DRAW:
12338 {
12339 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12340 for(int cset=0; cset<=13; cset++)
12341 {
12342 for(int color=0; color<16; color++)
12343 {
12344 rectfill(bmp,
12345 d->x+2+color*colorWidth,
12346 d->y+2+cset*colorHeight,
12347 d->x+2+((color+1)*colorWidth)-1,
12348 d->y+2+((cset+1)*colorHeight)-1,
12349 cset*16+color);
12350 }
12351 }
12352 }
12353 break;
12354
12355 case MSG_LPRESS:
12356 {
12357 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12358 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12359 massRecolorDraggedColor=cset*16+color;
12360 }
12361 break;
12362 }
12363
12364 return D_O_K;
12365 }
12366
12367 static DIALOG recolor_4bit_dlg[] =
12368 {
12369 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12370 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12371
12372 // 1
12373 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12374 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12375 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12376 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12377
12378 // 5
12379 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12380 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12381 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12382 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12383 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12384 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12385 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12386 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12387 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12388 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12389 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12390 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12391 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12392 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12393 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12394
12395 // 20
12396 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12397 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12398 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12399 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12400 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12401
12402 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12403 };
12404
12405 #define MR4_SRC_COLORS 2
12406 #define MR4_DEST_COLORS 4
12407 #define MR4_8BIT_EFFECT_START 6
12408 #define MR4_IGNORE_BLANK 20
12409 #define MR4_RESET 21
12410 #define MR4_SWITCH 22
12411 #define MR4_OK 23
12412 #define MR4_CANCEL 24
12413
12414 static DIALOG recolor_8bit_dlg[] =
12415 {
12416 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12417 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12418
12419 // 1
12420 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12421 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12422 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12423 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12424 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12425
12426 // 6
12427 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12428 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12429 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12430 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12431 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12432
12433 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12434 };
12435
12436 #define MR8_SRC_COLORS 2
12437 #define MR8_DEST_COLORS 4
12438 #define MR8_PALETTE 5
12439 #define MR8_IGNORE_BLANK 6
12440 #define MR8_RESET 7
12441 #define MR8_SWITCH 8
12442 #define MR8_OK 9
12443 #define MR8_CANCEL 10
12444
12445 static void massRecolorInit(int32_t cset)
12446 {
12447 massRecolorDraggedColor=-1;
12448 massRecolorCSet=cset;
12449
12450 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12451 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12452
12453 for(int32_t i=0; i<=13; i++)
12454 {
12455 if((massRecolor8BitCSets&(1<<i))!=0)
12456 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12457 else
12458 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12459 }
12460
12461 if(massRecolorIgnoreBlank)
12462 {
12463 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12464 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12465 }
12466 else
12467 {
12468 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12469 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12470 }
12471
12472 large_dialog(recolor_4bit_dlg);
12473 large_dialog(recolor_8bit_dlg);
12474
12475 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12476 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12477 {
12478 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12479 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12480 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12481 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12482
12483 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12484 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12485 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12486 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12487 recolor_8bit_dlg[MR8_PALETTE].x++;
12488 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12489 recolor_8bit_dlg[MR8_PALETTE].y++;
12490 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12491 }
12492 }
12493
12494 static void massRecolorApplyChanges()
12495 {
12496 massRecolor8BitCSets=0;
12497 for(int32_t i=0; i<=13; i++)
12498 {
12499 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12500 massRecolor8BitCSets|=1<<i;
12501 }
12502
12503 if(massRecolorType==MR_4BIT)
12504 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12505 else
12506 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12507 }
12508
12509 static bool massRecolorSetup(int32_t cset)
12510 {
12511 massRecolorInit(cset);
12512
12513 // Remember the current colors in case the user cancels.
12514 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12515 for(int32_t i=0; i<16; i++)
12516 {
12517 oldDest4Bit[i]=massRecolorDest4Bit[i];
12518 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12519 oldDest8Bit[i]=massRecolorDest8Bit[i];
12520 }
12521
12522 byte type=massRecolorType;
12523 int32_t ret;
12524 do
12525 {
12526 HANDLE_CLOSE_ZQDLG();
12527 if(exiting_program) break;
12528 if(type==MR_4BIT)
12529 {
12530 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12531 if(ret==MR4_SWITCH)
12532 type=MR_8BIT;
12533 }
12534 else
12535 {
12536 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12537 if(ret==MR8_SWITCH)
12538 type=MR_4BIT;
12539 }
12540 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12541
12542 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12543 {
12544 for(int32_t i=0; i<16; i++)
12545 {
12546 massRecolorDest4Bit[i]=oldDest4Bit[i];
12547 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12548 massRecolorDest8Bit[i]=oldDest8Bit[i];
12549 }
12550 return false;
12551 }
12552
12553 // OK
12554 massRecolorType=type;
12555 massRecolorApplyChanges();
12556 return true;
12557 }
12558
12559 static void massRecolorApply4Bit(int32_t tile)
12560 {
12561 byte buf[256];
12562 unpack_tile(newtilebuf, tile, 0, true);
12563
12564 if(newtilebuf[tile].format==tf4Bit)
12565 {
12566 for(int32_t i=0; i<256; i++)
12567 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12568 }
12569 else // 8-bit
12570 {
12571 for(int32_t i=0; i<256; i++)
12572 {
12573 word cset=unpackbuf[i]>>4;
12574 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12575 {
12576 word color=unpackbuf[i]&15;
12577 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12578 }
12579 else
12580 buf[i]=unpackbuf[i];
12581 }
12582 }
12583
12584 pack_tile(newtilebuf, buf, tile);
12585 }
12586
12587 static void massRecolorApply8Bit(int32_t tile)
12588 {
12589 byte buf[256];
12590 unpack_tile(newtilebuf, tile, 0, true);
12591
12592 for(int32_t i=0; i<256; i++)
12593 {
12594 byte color=unpackbuf[i];
12595 for(int32_t j=0; j<16; j++)
12596 {
12597 if(massRecolorSrc8Bit[j]==color)
12598 {
12599 color=massRecolorDest8Bit[j];
12600 break;
12601 }
12602 }
12603 buf[i]=color;
12604 }
12605
12606 pack_tile(newtilebuf, buf, tile);
12607 }
12608
12609 static void massRecolorApply(int32_t tile)
12610 {
12611 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12612 return;
12613
12614 if(massRecolorType==MR_4BIT)
12615 massRecolorApply4Bit(tile);
12616 else // 8-bit
12617 {
12618 if(newtilebuf[tile].format==tf4Bit)
12619 return;
12620 massRecolorApply8Bit(tile);
12621 }
12622 }
12623
12624 static void massRecolorReset4Bit()
12625 {
12626 for(int32_t i=0; i<16; i++)
12627 massRecolorDest4Bit[i]=i;
12628 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12629 }
12630
12631 static void massRecolorReset8Bit()
12632 {
12633 for(int32_t i=0; i<16; i++)
12634 {
12635 massRecolorSrc8Bit[i]=0;
12636 massRecolorDest8Bit[i]=0;
12637 }
12638
12639 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12640 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12641 }
12642
12643 6 void center_zq_tiles_dialogs()
12644 {
12645 6 jwin_center_dialog(create_relational_tiles_dlg);
12646 6 jwin_center_dialog(icon_dlg);
12647 6 jwin_center_dialog(leech_dlg);
12648 6 jwin_center_dialog(move_textbox_list_dlg);
12649 6 jwin_center_dialog(recolor_4bit_dlg);
12650 6 jwin_center_dialog(recolor_8bit_dlg);
12651 6 }
12652
12653 //.ZCOMBO
12654
12655 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12656 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12657
12658 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12659 dword section_version, dword section_cversion, int32_t index, int32_t count)
12660 {
12661 newcombo temp_combo;
12662 for ( int32_t tilect = 0; tilect < count; tilect++ )
12663 {
12664 temp_combo.clear();
12665 if(!p_igetw(&temp_combo.tile,f))
12666 {
12667 return 0;
12668 }
12669 temp_combo.o_tile = temp_combo.tile;
12670
12671 if(!p_getc(&temp_combo.flip,f))
12672 {
12673 return 0;
12674 }
12675
12676 if(!p_getc(&temp_combo.walk,f))
12677 {
12678 return 0;
12679 }
12680
12681 if(!p_getc(&temp_combo.type,f))
12682 {
12683 return 0;
12684 }
12685
12686 if(!p_getc(&temp_combo.csets,f))
12687 {
12688 return 0;
12689 }
12690
12691 if(!p_getc(&temp_combo.frames,f))
12692 {
12693 return 0;
12694 }
12695
12696 if(!p_getc(&temp_combo.speed,f))
12697 {
12698 return 0;
12699 }
12700
12701 if(!p_igetw(&temp_combo.nextcombo,f))
12702 {
12703 return 0;
12704 }
12705
12706 if(!p_getc(&temp_combo.nextcset,f))
12707 {
12708 return 0;
12709 }
12710
12711 if(!p_getc(&temp_combo.flag,f))
12712 {
12713 return 0;
12714 }
12715
12716 if(!p_getc(&temp_combo.skipanim,f))
12717 {
12718 return 0;
12719 }
12720
12721 if(!p_igetw(&temp_combo.nexttimer,f))
12722 {
12723 return 0;
12724 }
12725
12726 if(!p_getc(&temp_combo.skipanimy,f))
12727 {
12728 return 0;
12729 }
12730
12731 if(!p_getc(&temp_combo.animflags,f))
12732 {
12733 return 0;
12734 }
12735
12736 //2.55 starts here
12737 if ( zversion >= 0x255 )
12738 {
12739 if ( section_version >= 12 )
12740 {
12741 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12742 {
12743 if(!p_igetl(&temp_combo.attributes[q],f))
12744 {
12745 return 0;
12746 }
12747 }
12748 if(!p_igetl(&temp_combo.usrflags,f))
12749 {
12750 return 0;
12751 }
12752 for ( int32_t q = 0; q < 3; q++ )
12753 {
12754 if(!p_igetl(&temp_combo.triggerflags[q],f))
12755 {
12756 return 0;
12757 }
12758 }
12759
12760 if(!p_igetl(&temp_combo.triggerlevel,f))
12761 {
12762 return 0;
12763 }
12764 if(section_version >= 22)
12765 {
12766 if(!p_getc(&temp_combo.triggerbtn,f))
12767 {
12768 return 0;
12769 }
12770 }
12771 if(section_version < 23)
12772 {
12773 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12774 {
12775 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12776 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12777 case cTRIGGERGENERIC: case cCSWITCH:
12778 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12779 }
12780 }
12781 if(section_version >= 24)
12782 {
12783 if(!p_getc(&temp_combo.triggeritem,f))
12784 {
12785 return 0;
12786 }
12787 if(!p_getc(&temp_combo.trigtimer,f))
12788 {
12789 return 0;
12790 }
12791 }
12792 if(section_version >= 25)
12793 {
12794 if(!p_getc(&temp_combo.trigsfx,f))
12795 {
12796 return 0;
12797 }
12798 }
12799 else
12800 {
12801 switch(temp_combo.type)
12802 {
12803 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12804 if(!(temp_combo.usrflags & cflag3))
12805 temp_combo.attribytes[3] = WAV_DOOR;
12806 temp_combo.usrflags &= ~cflag3;
12807 break;
12808 }
12809 }
12810 if(section_version < 26)
12811 {
12812 if(temp_combo.type == cARMOS)
12813 {
12814 if(temp_combo.usrflags & cflag1)
12815 temp_combo.usrflags |= cflag3;
12816 }
12817 }
12818 if(section_version >= 27)
12819 {
12820 if(!p_igetl(&temp_combo.trigchange,f))
12821 {
12822 return qe_invalid;
12823 }
12824 }
12825 else
12826 {
12827 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12828 temp_combo.trigchange = 1;
12829 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12830 temp_combo.trigchange = -1;
12831 else temp_combo.trigchange = 0;
12832 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12833 }
12834 if(section_version >= 29)
12835 {
12836 if(!p_igetw(&temp_combo.trigprox,f))
12837 {
12838 return qe_invalid;
12839 }
12840 if(!p_getc(&temp_combo.trigctr,f))
12841 {
12842 return qe_invalid;
12843 }
12844 if(!p_igetl(&temp_combo.trigctramnt,f))
12845 {
12846 return qe_invalid;
12847 }
12848 }
12849 else
12850 {
12851 temp_combo.trigprox = 0;
12852 temp_combo.trigctr = 0;
12853 temp_combo.trigctramnt = 0;
12854 }
12855 if(section_version >= 30)
12856 {
12857 if(!p_getc(&temp_combo.triglbeam,f))
12858 {
12859 return qe_invalid;
12860 }
12861 }
12862 else temp_combo.triglbeam = 0;
12863 if(section_version >= 31)
12864 {
12865 if(!p_getc(&temp_combo.trigcschange,f))
12866 {
12867 return qe_invalid;
12868 }
12869 if(!p_igetw(&temp_combo.spawnitem,f))
12870 {
12871 return qe_invalid;
12872 }
12873 if(!p_igetw(&temp_combo.spawnenemy,f))
12874 {
12875 return qe_invalid;
12876 }
12877 if(!p_getc(&temp_combo.exstate,f))
12878 {
12879 return qe_invalid;
12880 }
12881 if(!p_igetl(&temp_combo.spawnip,f))
12882 {
12883 return qe_invalid;
12884 }
12885 if(!p_getc(&temp_combo.trigcopycat,f))
12886 {
12887 return qe_invalid;
12888 }
12889 }
12890 else
12891 {
12892 temp_combo.trigcschange = 0;
12893 temp_combo.spawnitem = 0;
12894 temp_combo.spawnenemy = 0;
12895 temp_combo.exstate = -1;
12896 temp_combo.spawnip = 0;
12897 temp_combo.trigcopycat = 0;
12898 }
12899 if(section_version >= 32)
12900 {
12901 if(!p_getc(&temp_combo.trigcooldown,f))
12902 {
12903 return qe_invalid;
12904 }
12905 }
12906 else
12907 {
12908 temp_combo.trigcooldown = 0;
12909 }
12910 char label[12];
12911 label[11] = '\0';
12912 for ( int32_t q = 0; q < 11; q++ )
12913 {
12914 if(!p_getc(&label[q],f))
12915 {
12916 return 0;
12917 }
12918 }
12919 temp_combo.label = label;
12920 }
12921 if ( section_version >= 13 )
12922 {
12923 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12924 {
12925 if(!p_getc(&temp_combo.attribytes[q],f))
12926 {
12927 return 0;
12928 }
12929 }
12930
12931 }
12932 }
12933
12934 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12935 {
12936 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12937 {
12938 combobuf[index+(tilect)] = temp_combo;
12939 }
12940 }
12941 }
12942
12943 return 1;
12944 }
12945
12946 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12947 {
12948 dword section_version=0;
12949 dword section_cversion=0;
12950 int32_t zversion = 0;
12951 int32_t zbuild = 0;
12952
12953 if(!p_igetl(&zversion,f))
12954 {
12955 return 0;
12956 }
12957 if(!p_igetl(&zbuild,f))
12958 {
12959 return 0;
12960 }
12961 if(!p_igetw(&section_version,f))
12962 {
12963 return 0;
12964 }
12965 if(!p_igetw(&section_cversion,f))
12966 {
12967 return 0;
12968 }
12969
12970 if ( zversion > ZELDA_VERSION )
12971 {
12972 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12973 return 0;
12974 }
12975
12976 else if ( ( section_version > V_COMBOS ) || ( section_version == V_COMBOS && section_cversion > CV_COMBOS ) )
12977 {
12978 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d) subversion (%d)\n", section_version, section_cversion);
12979 return 0;
12980
12981 }
12982 else
12983 {
12984 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
12985 }
12986
12987 int32_t index = 0;
12988 int32_t count = 0;
12989
12990 //tile id
12991 if(!p_igetl(&index,f))
12992 {
12993 return 0;
12994 }
12995 if(start > -1) index = start;
12996 // al_trace("Reading combo: index(%d)\n", index);
12997
12998 //tile count
12999 if(!p_igetl(&count,f))
13000 {
13001 return 0;
13002 }
13003 // al_trace("Reading combo: count(%d)\n", count);
13004 reset_combo_animations();
13005 reset_combo_animations2();
13006
13007 if(section_version < 33)
13008 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,section_cversion,index,count);
13009
13010 newcombo temp_combo;
13011 size_t end = index+count;
13012 for ( size_t q = index; q < end; q++ )
13013 {
13014 auto ret = readcombo_loop(f,section_version,temp_combo);
13015 if(ret) return 0;
13016
13017 if ( !(skip && q-1 < skip) )
13018 {
13019 if ( !nooverwrite || combobuf[q].is_blank() )
13020 {
13021 combobuf[q] = temp_combo;
13022 }
13023 }
13024 }
13025
13026 return 1;
13027 }
13028 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13029 {
13030 return readcombofile(f,skip,nooverwrite,start);
13031 }
13032 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13033 {
13034 dword section_version=V_COMBOS;
13035 dword section_cversion=CV_COMBOS;
13036 int32_t zversion = ZELDA_VERSION;
13037 int32_t zbuild = VERSION_BUILD;
13038
13039 if(!p_iputl(zversion,f))
13040 {
13041 return 0;
13042 }
13043 if(!p_iputl(zbuild,f))
13044 {
13045 return 0;
13046 }
13047 if(!p_iputw(section_version,f))
13048 {
13049 return 0;
13050 }
13051
13052 if(!p_iputw(section_cversion,f))
13053 {
13054 return 0;
13055 }
13056
13057 //start tile id
13058 if(!p_iputl(index,f))
13059 {
13060 return 0;
13061 }
13062
13063 //count
13064 if(!p_iputl(count,f))
13065 {
13066 return 0;
13067 }
13068 reset_combo_animations();
13069 reset_combo_animations2();
13070 size_t end = index+count;
13071 for(size_t q = index; q < end; ++q)
13072 {
13073 if(writecombo_loop(f, section_version, combobuf[q]))
13074 return 0;
13075 }
13076
13077 return 1;
13078
13079 }
13080
13081 //.ZALIAS
13082
13083
13084 //.ZALIAS
13085
13086 int32_t readcomboaliasfile(PACKFILE *f)
13087 {
13088 dword section_version=0;
13089 dword section_cversion=0;
13090 int32_t zversion = 0;
13091 int32_t zbuild = 0;
13092 word tempword = 0;
13093
13094 if(!p_igetl(&zversion,f))
13095 {
13096 return 0;
13097 }
13098 if(!p_igetl(&zbuild,f))
13099 {
13100 return 0;
13101 }
13102 if(!p_igetw(&section_version,f))
13103 {
13104 return 0;
13105 }
13106 if(!p_igetw(&section_cversion,f))
13107 {
13108 return 0;
13109 }
13110 al_trace("readoneweapon section_version: %d\n", section_version);
13111 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
13112
13113 if ( zversion > ZELDA_VERSION )
13114 {
13115 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13116 return 0;
13117 }
13118
13119 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13120 {
13121 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13122 return 0;
13123
13124 }
13125 else
13126 {
13127 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13128 }
13129
13130 int32_t index = 0;
13131 int32_t count = 0;
13132 int32_t count2 = 0;
13133 byte tempcset = 0;
13134
13135 //tile id
13136 if(!p_igetl(&index,f))
13137 {
13138 return 0;
13139 }
13140 al_trace("Reading combo: index(%d)\n", index);
13141
13142 //tile count
13143 if(!p_igetl(&count,f))
13144 {
13145 return 0;
13146 }
13147 al_trace("Reading combo: count(%d)\n", count);
13148
13149 combo_alias temp_alias;
13150 memset(&temp_alias, 0, sizeof(temp_alias));
13151
13152 for ( int32_t tilect = 0; tilect < count; tilect++ )
13153 {
13154 memset(&temp_alias, 0, sizeof(temp_alias));
13155 if(!p_igetw(&temp_alias.combo,f))
13156 {
13157 return 0;
13158 }
13159
13160 if(!p_getc(&temp_alias.cset,f))
13161 {
13162 return 0;
13163 }
13164
13165
13166
13167 if(!p_igetl(&count2,f))
13168 {
13169 return 0;
13170 }
13171 al_trace("Read, Combo alias count is: %d\n", count2);
13172 if(!p_getc(&temp_alias.width,f))
13173 {
13174 return 0;
13175 }
13176
13177 if(!p_getc(&temp_alias.height,f))
13178 {
13179 return 0;
13180 }
13181
13182 if(!p_getc(&temp_alias.layermask,f))
13183 {
13184 return 0;
13185 }
13186 //These values are flexible, and may differ in size, so we delete them
13187 //and recreate them at the correct size on the pointer.
13188 temp_alias.combos.clear();
13189 temp_alias.csets.clear();
13190 for(int32_t k=0; k<count2; k++)
13191 {
13192 if(!p_igetw(&tempword,f))
13193 {
13194 return 0;
13195 }
13196 else
13197 {
13198
13199
13200 temp_alias.combos[k] = tempword;
13201 }
13202 }
13203
13204 for(int32_t k=0; k<count2; k++)
13205 {
13206 if(!p_getc(&tempcset,f))
13207 //if(!p_getc(&temp_alias.csets[k],f))
13208 {
13209 return 0;
13210 }
13211 else
13212 {
13213
13214 temp_alias.csets[k] = tempcset;
13215 }
13216 }
13217 memcpy(&combo_aliases[index+(tilect)],&temp_alias,sizeof(combo_alias));
13218 }
13219
13220 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13221
13222
13223 return 1;
13224
13225 }
13226
13227 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13228 {
13229 dword section_version=0;
13230 dword section_cversion=0;
13231 int32_t zversion = 0;
13232 int32_t zbuild = 0;
13233
13234 if(!p_igetl(&zversion,f))
13235 {
13236 return 0;
13237 }
13238 if(!p_igetl(&zbuild,f))
13239 {
13240 return 0;
13241 }
13242 if(!p_igetw(&section_version,f))
13243 {
13244 return 0;
13245 }
13246 if(!p_igetw(&section_cversion,f))
13247 {
13248 return 0;
13249 }
13250 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13251 al_trace("readcomboaliasfile_to_location section_cversion: %d\n", section_cversion);
13252
13253 if ( zversion > ZELDA_VERSION )
13254 {
13255 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13256 return 0;
13257 }
13258 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13259 {
13260 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13261 return 0;
13262
13263 }
13264 else
13265 {
13266 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13267 }
13268
13269 int32_t index = 0;
13270 int32_t count = 0;
13271 int32_t count2 = 0;
13272 byte tempcset = 0;
13273 word tempword = 0;
13274
13275
13276 //tile id
13277 if(!p_igetl(&index,f))
13278 {
13279 return 0;
13280 }
13281 al_trace("Reading tile: index(%d)\n", index);
13282
13283 //tile count
13284 if(!p_igetl(&count,f))
13285 {
13286 return 0;
13287 }
13288 al_trace("Reading tile: count(%d)\n", count);
13289
13290
13291 combo_alias temp_alias;
13292 memset(&temp_alias, 0, sizeof(temp_alias));
13293
13294 for ( int32_t tilect = 0; tilect < count; tilect++ )
13295 {
13296 memset(&temp_alias, 0, sizeof(temp_alias));
13297 if(!p_igetw(&temp_alias.combo,f))
13298 {
13299 return 0;
13300 }
13301
13302 if(!p_getc(&temp_alias.cset,f))
13303 {
13304 return 0;
13305 }
13306
13307 int32_t count2 = 0;
13308
13309 if(!p_igetl(&count2,f))
13310 {
13311 return 0;
13312 }
13313
13314 if(!p_getc(&temp_alias.width,f))
13315 {
13316 return 0;
13317 }
13318
13319 if(!p_getc(&temp_alias.height,f))
13320 {
13321 return 0;
13322 }
13323
13324 if(!p_getc(&temp_alias.layermask,f))
13325 {
13326 return 0;
13327 }
13328 //These values are flexible, and may differ in size, so we delete them
13329 //and recreate them at the correct size on the pointer.
13330 temp_alias.combos.clear();
13331 temp_alias.csets.clear();
13332
13333 for(int32_t k=0; k<count2; k++)
13334 {
13335 if(!p_igetw(&tempword,f))
13336 {
13337 return 0;
13338 }
13339 else
13340 {
13341 temp_alias.combos[k] = tempword;
13342 }
13343 }
13344
13345 for(int32_t k=0; k<count2; k++)
13346 {
13347 if(!p_getc(&tempcset,f))
13348 {
13349 return 0;
13350 }
13351 else
13352 {
13353 temp_alias.csets[k] = tempcset;
13354 }
13355 }
13356
13357 if ( start+(tilect) < MAXCOMBOALIASES )
13358 {
13359 memcpy(&combo_aliases[start+(tilect)],&temp_alias,sizeof(temp_alias));
13360 }
13361 }
13362 return 1;
13363 }
13364 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13365 {
13366 al_trace("Running writecomboaliasfile\n");
13367 dword section_version=V_COMBOALIASES;
13368 dword section_cversion=CV_COMBOALIASES;
13369 int32_t zversion = ZELDA_VERSION;
13370 int32_t zbuild = VERSION_BUILD;
13371
13372 if(!p_iputl(zversion,f))
13373 {
13374 return 0;
13375 }
13376 if(!p_iputl(zbuild,f))
13377 {
13378 return 0;
13379 }
13380 if(!p_iputw(section_version,f))
13381 {
13382 return 0;
13383 }
13384
13385 if(!p_iputw(section_cversion,f))
13386 {
13387 return 0;
13388 }
13389
13390 //start tile id
13391 if(!p_iputl(index,f))
13392 {
13393 return 0;
13394 }
13395
13396 //count
13397 if(!p_iputl(count,f))
13398 {
13399 return 0;
13400 }
13401
13402 for ( int32_t tilect = 0; tilect < count; tilect++ )
13403 {
13404
13405 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13406 {
13407 return 0;
13408 }
13409
13410 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13411 {
13412 return 0;
13413 }
13414
13415 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13416
13417 if(!p_iputl(count2,f))
13418 {
13419 return 0;
13420 }
13421 al_trace("Write`, Combo alias count is: %d\n", count2);
13422
13423 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13424 {
13425 return 0;
13426 }
13427
13428 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13429 {
13430 return 0;
13431 }
13432
13433 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13434 {
13435 return 0;
13436 }
13437
13438 for(int32_t k=0; k<count2; k++)
13439 {
13440 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13441 {
13442 return 0;
13443 }
13444 }
13445
13446 for(int32_t k=0; k<count2; k++)
13447 {
13448 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13449 {
13450 return 0;
13451 }
13452 }
13453 }
13454
13455 return 1;
13456
13457 }
13458